$30 off During Our Annual Pro Sale. View Details »

Paying Down Debt

Samuel E. Giddins
September 04, 2015
53

Paying Down Debt

Closing talk given at iOS Dev Camp DC 2015.

Samuel E. Giddins

September 04, 2015
Tweet

Transcript

  1. Paying Down Debt Samuel Giddins

  2. Samuel Giddins Realm, CocoaPods, Bundler, etc.

  3. git blame

  4. git log | tail -n 30 commit ed68b4631621be8a09786eeef9653a4fde2028e8 Author: Eloy

    Duran <eloy.de.enige@gmail.com> Date: Sat Aug 13 23:00:15 2011 +0200 More work on README. commit 3e80b4cad120e35d23d9a44cdf7eb52ec70beac3 Author: Eloy Duran <eloy.de.enige@gmail.com> Date: Sat Aug 13 17:40:11 2011 +0200 Rename a bit commit 5889b9bbdf22e30782821e507c3ec0d83d4ec602 Author: Eloy Duran <eloy.de.enige@gmail.com> Date: Sat Aug 13 17:39:00 2011 +0200 Add an example PodSpec.rb file commit 8aa61846580eb4ade7a92d3031d3ac4813bb94ef Author: Eloy Duran <eloy.de.enige@gmail.com> Date: Sat Aug 13 02:14:56 2011 +0200 Add notes about kit commit fd2bc0a7cc4c49ddc37edb2a16398f8cfb06132e Author: Eloy Duran <eloy.de.enige@gmail.com> Date: Sat Aug 13 01:58:11 2011 +0200 Initial import
  5. cloc $(git ls-files) 319 text files. 318 unique files. 50

    files ignored. http://cloc.sourceforge.net v 1.62 T=0.41 s (656.7 files/s, 95326.7 lines/s) -------------------------------------------------------------------------------- Language files blank comment code -------------------------------------------------------------------------------- Ruby 265 6664 3330 28660 YAML 3 72 101 211 Bourne Again Shell 1 2 1 5 -------------------------------------------------------------------------------- SUM: 269 6738 3432 28876 --------------------------------------------------------------------------------
  6. commit 9d3890e96f0ebbd358f5f2d5ee619dea7f8e7310 Author: Samuel E. Giddins <segiddins@segiddins.me> Date: Mon Aug

    24 11:50:51 2015 -0700 Avoid deadlocks in standalone object initialization diff --git a/Realm/RLMAccessor.mm b/Realm/RLMAccessor.mm index a9525fe..537caee 100644 --- a/Realm/RLMAccessor.mm +++ b/Realm/RLMAccessor.mm @@ -597,6 +597,12 @@ void RLMReplaceSharedSchemaMethod(Class accessorClass, RLMObjectSchema *schema) class_replaceMethod(metaClass, @selector(sharedSchema), imp, "@@:"); } +void RLMReplaceSharedSchemaMethodWithBlock(Class accessorClass, RLMObjectSchema *(^method)(Class)) { + Class metaClass = objc_getMetaClass(class_getName(accessorClass)); + IMP imp = imp_implementationWithBlock(method); + class_replaceMethod(metaClass, @selector(sharedSchema), imp, "@@:"); +} + static Class RLMCreateAccessorClass(Class objectClass, RLMObjectSchema *schema, NSString *accessorClassPrefix, diff --git a/Realm/RLMObjectBase.h b/Realm/RLMObjectBase.h index 8184c2c..925e8e5 100644 --- a/Realm/RLMObjectBase.h +++ b/Realm/RLMObjectBase.h @@ -33,7 +33,7 @@ RLM_ASSUME_NONNULL_BEGIN + (NSString *)className; -/// Returns whether the class is included in the default set of classes persisted in a Realm. +// Returns whether the class is included in the default set of classes persisted in a Realm. + (BOOL)shouldIncludeInDefaultSchema; @end diff --git a/Realm/RLMSchema.mm b/Realm/RLMSchema.mm index d4c5f8f..2d9f514 100644 --- a/Realm/RLMSchema.mm +++ b/Realm/RLMSchema.mm @@ -41,8 +41,8 @@ const uint64_t RLMNotVersioned = realm::ObjectStore::NotVersioned; @end static RLMSchema *s_sharedSchema; -static RLMSchema *s_partialSharedSchema; -static NSMutableDictionary *s_localNameToClass; +static RLMSchema *s_partialSharedSchema = [[RLMSchema alloc] init]; +static NSMutableDictionary *s_localNameToClass = [[NSMutableDictionary alloc] init]; @implementation RLMSchema @@ -85,23 +85,13 @@ static NSMutableDictionary *s_localNameToClass; } } -+ (void)initialize { - static bool initialized; - if (initialized) { - return; - } - initialized = true; - - s_localNameToClass = [NSMutableDictionary dictionary]; - s_partialSharedSchema = [[RLMSchema alloc] init]; -} - + (instancetype)partialSharedSchema { return s_partialSharedSchema; } + (void)registerClasses:(Class *)classes count:(NSUInteger)count { @synchronized(s_localNameToClass) { + auto threadID = pthread_mach_thread_np(pthread_self()); // first create class to name mapping so we can do array validation // when creating object schema for (NSUInteger i = 0; i < count; i++) { @@ -134,8 +124,17 @@ static NSMutableDictionary *s_localNameToClass; s_localNameToClass[className] = cls; RLMReplaceClassNameMethod(cls, className); - // override sharedSchema classs method to return nil to avoid topo-sort issues - RLMReplaceSharedSchemaMethod(cls, nil); + // override sharedSchema classs method to return nil to avoid topo-sort issues when on this thread + // (i.e. while during schema initialization), but wait on other threads until schema initialization is done, + // then return the just-initialized schema + RLMReplaceSharedSchemaMethodWithBlock(cls, ^RLMObjectSchema *(Class cls) { + if (threadID == pthread_mach_thread_np(pthread_self())) { + return nil; + } + @synchronized(s_localNameToClass) { + return [cls sharedSchema]; + } + }); }
  7. Technical Debt

  8. Debt

  9. Debt finances construction

  10. None
  11. No Silver Bullets

  12. Techniques: — Slash & Burn — Quarantine — Zero regressions

    — Boy Scouting
  13. None
  14. Slash & Burn

  15. ! it all

  16. None
  17. New Is Always Better

  18. Old Things Still Have Value

  19. Coding best practice: if you see code you don’t immediately

    understand “why” you should delete it and see what happens. — @Dirk_Gently
  20. Deleted Code == Best Code

  21. But what if I can't !! it all?

  22. Quarantine

  23. None
  24. ! Up The Evil

  25. Object-oriented programming is an exceptionally bad idea which could only

    have originated in California. — Edsger Dijkstra
  26. Make it possible to replace the bad code later

  27. But what if I don't have time to refactor now?

  28. Zero Regressions

  29. One-Way Flow of Progress

  30. We have a zero-tolerance policy for performance regressions. If a

    patch lands that regresses performance according to our benchmarks, then the person responsible must either back the patch out of the tree or drop everything immediately and fix the regression.
  31. Common excuses people give when they regress performance are, "But

    the new way is cleaner!" or "The new way is more correct." We don't care. No performance regressions are allowed, regardless of the reason. There is no justification for regressing performance. None.
  32. The way to make a program faster is to never

    let it get slower.
  33. But what if I'm not allowed to implement a policy

    that strong?
  34. Boy Scouting

  35. None
  36. Pick up the messes you find

  37. None
  38. None
  39. Little by little, the project will become cleaner

  40. But what if...

  41. What about tests?

  42. Tests are a !

  43. Selling It

  44. Bosses, amirite?

  45. But now is crunch time! We can do that later.

  46. No turning back time

  47. None
  48. Be assured that it gives much more pain to the

    mind to be in debt, than to do without any article whatever which we may seem to want. — Thomas Jefferson
  49. With balance, we can build amazing things that will last

  50. None
  51. Samuel Giddins @segiddins