Sunday, July 12, 2015

Main iOS Architecture and Patterns

Main iOS Architecture and Patterns

The following design patterns are present in many of apple's iOS frameworks:

  1. Target-Action: Can be used to connect a UI control to an implementation of what it does upon being activated by the user.  You can see this pattern in Storyboards when dragging from a control to the code and creating an "Action". Even if your UI classes come from different parents, for example: UIBarButtonItem vs UIButton, they still both use the Target-Action mechanism to handle their pressed events.  The same target-action mechanism is used by gesture recognizers.  A message is also sent along with the action to the target. 

  2. Responder-Chain:  Lets your application handle events without knowing which particular object will handle them. An initiator kicks off an action to the first responder.  That responder may or may not respond to it, or forward it on to the next responder. Typical responder chain (Default view hierarchy):  View-->ViewController-->Window-->Applicastion-->AppDelegate. 

  3.  Composite: Manipulate a group of objects as a single object.  Example: create two views: A and B.  Add B as a subview to A. Now manipulating A will also operate on B, because B is inside A's composite.  Now also B's nextResponder is A, because that is its super view.  UIDynamicBehavior is another place where the same pattern is found: a child behaviour can be added to your dynamicBehavior.  Now the physics simulation running in the background will manipulate the parent dynamicBehavior object as a composite, affecting all nested behaviors inside (nested tree) as one object. 

  4. Delegation: Customize behavior without subclassing the customized object.  For example: UIApplication --> UIApplicationDelegate.   The App Delegate specifies behaviour for various methods of your application.  The app delegate doesn't have to know anything else about the UIApplication.  It only needs to know how to react to 7 application life cycle events.  If you had to override UIApplication instead of receiving it's delegated events, you would have to understand how UIApplication works:  
    1. Which methods must you override?
    2. Which methods are optional?
    3. Do you have to call super on overridden methods?

    4. Other examples of Delegates:
      AVAssetResourceLoader --> AVAssetResourceLoaderDelegate
      CALayer --> CALayerDelegate
      GKSession --> GKSessionDelegate 

  5. Data Source: Customize the data retrieval without having to subclass the object that needs the data.  Example:  UITableView --> UITableViewDataSource.  The tableView asks you for things that it needs from the data source, such as: number of rows, number of sections, view for row, etc.  Other examples: 
    1. UICollectionView --> UICollectionViewDataSource
    2. UIPageViewController --> UIPageViewControllerDataSource
    3. UIPickerView --> UIPickerViewDataSource

  6. Model-View-Controller:  Build organizational structure around application's responsibilities. The model is your business data definition, and possibly functionality related to that particular entity.  The view is your UI which fires events to perform certain actions.  The controller handles the View's actions, reads models, returns data to Views, and does everything else necessary to allow the View to do its job, and update the models accordingly. 
The below steps are a good general process when building a simple application: 

1. The Human Interface Guideline

https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/
Should use this as a guide when designing an application. 

2. Application Definition Statement

Important to come up with a focused application statement.  It's a 30 second elevator pitch of exactly what the application is and who it's for.  For example:  "Allow people to share simple, short updates about what is happening in their lives".  The come up with a list of features that are likely to be used.  In this case:  Networked, Lists of data, Good performance, Add an entry, Add photos, Mark items, Edit posts.  Then figure out what to say No to.   So according to our above application statement, we would drop the following 3:  Add photos, Mark items and Edit posts, because they do not fit into the statement. 

3. Come up with simple wire-frames of all screens. 

This will help visualize layout, content, models and ui controls needed.

4. Define Models

Based on the user story statements, pull out the nouns, and that will likely tell you what models will be used. 

5. Define Views

For example:  Use a tableview. Have table view cells with wrappable text fields and images.  Use UIBarButtonItem to display the + button in the Top right, to create an entry. 

6. Define ViewController

Most likely our View Controller will serve as a data source to our table view.  It will also have actions, such as the "add new entry".  In a simple example, VC also has to manage the networking, such as using NSURLConnection, to retrieve model data, and expose it to the views.  However, ideally we don't want the VC to know anything about the networking layer, and instead use a Query object to retrieve the data. 





Saturday, July 11, 2015

Strategies that produce Great Software

Strategies that produce Great Software

based on the Apple WWDC 2014 Video by: Ken Kocienda
  1. When adopting 3rd party controls, try to get a demo as soon as possible.  The ease in adoption of the framework will tell how likely it is to be useful in your project.  Rather than striving for code-complete perfect implementation, make a minimal viable product to demo and throw stones at, so that an understanding of feasibility can be made, and the size of the gap to be bridged.  Know a good idea when you see it by testing the prototype. 

  2. Don't try to solve every single problem right away.  When adopting libraries, you might want to only use the parts you are going to use.  So pull out the parts you want, and only bring those in, rather than using the whole project which you will not use all of.  This process can take time, however, because likely the creator of the Third Party library did not intend this.  Have achievable goals.  For example, when Apple was integrating KHTML to build Safari WebKit for the first time, after integrating everything, only a "Black Obelisk" would show on the screen (black rectangle).   You won't be able to address every point in a huge problem right away.  Just try to get something drawing on the screen. 

  3. Ask for help if you don't feel like you're making sufficient progress.  Are you trying to use an API that is too low level for what you are trying to do?   If that's the case, consider building your own API which does exactly what you are trying to accomplish.  When framing the requirement from a higher abstraction, you will get the benefit of having the code structure organized.  So you may still need to use the low level APIs to get there, but at-least the higher Level API design helps you organize the code with clarity.  In other words if a low level API doesn't serve your purpose, build a higher level API abstraction around it, in order to simplify the interaction with the calling code.  (Facade or Bridge).  Get input from smart colleagues if you are stuck.  They will always have a different perspective. 

  4. It's great to be able to use something that people are aware of, so you don't have to train them. Everyone is familiar with the QWERTY keyboard.  Work should explain itself (by convention). 

  5. Choose the simplest idea which might work.  For example, when you type on a keyboard with Auto-correct, if you make the dictionary look up very fast (O logN), it might make sense to look up every combination of neighbouring letters next to the keys you pressed, and actually look up all those permutation - for any word length.  (Every word on every keystroke)

  6. Only show your best work.  Test out all the ideas, pick the best idea and really test it out. When the time to make the decision comes, you will have all the information to make the best decision.  When you have gone through all this effort, you will have your best work distilled into a Demo which will succeed. 

  7. Can we go faster than the iterative cycle of:  Demo to Designer, Make Changes, Demo Again etc...   Instead we can have "Tunable Values" to reduce iteration time.  This way the designer can make changes on the fly, such as "Make something 2% darker".  Every single value can be polished to perfection by the designer now.  The designer tunes it until he is completely satisfied, then you take the produced slider values and commit that to the code base.  This eliminates all the iterations which would have been needed, if tuning was not in place. Therefore: "Iterating quicker leads to better work". 

  8. Be kind to people, but be honest about their work.  Never raise your voice.  The people are most likely trying very hard to produce good work, but you still have to be honest and up-front about the quality of the work, and let them know that.  They will also not take your feedback personally.  You need to separate yourself from your work emotionally.  If your solution is viewed as that of poor quality, you shouldn't take it personally. It's just an opportunity for improvement.  

  9. You are never "done" in Technology.  It moves fast, and you need to keep up.  Try to do the best possible job at any given time.  Don't dwell too long on something that is pretty good, but rather move on to the next step.  Often times you will have to "Rewrite" your solution completely, while working on it.  This is because of valuable lessons you could have learned during development, or input from colleagues.  This is not a bad thing, rather: an opportunity for improvement and learning.  Technical humility is a great trait to have in this field. 
Learn how to create your own Programming Language here!!

Tuesday, July 7, 2015

What's New in XCode: WWDC 2014 (August)


Major Areas

  1. Swift
  2. Live Design
  3. Visual Debugging
  4. Performance Testing

 Swift Overview

  • A brand new language.  
  • Framework header files are available in Swift syntax.
  • Playgrounds allows executing your code more rapidly, as you are authoring it.
  • QuickHelp shows a short in-line description, at the time you are using auto-complete.
  • When using inferred types, such as "let x = ...", swift can tell you what the inferred type is that will be assigned, by using mouse over on the statement. 
  • Can have .h, .m and .swift files side by side, working together. 

Design Features Overview

  • XCode 6 now allows using storyboards to develop OS10 applications.
  • Using custom fonts will now show up in interface builder on the canvas. 
  • Sprite kit level editor lets us visually assemble scenes. 
  • New way to localize applications:  Export all localizable assets into XLIFF (XML Localization Interchange File Format), which is an industry standard format.  Then import the translated file back into XCode to merge in the localized content into the project.
  • @IBDesignable allows flagging your class for having certain elements show up in IB. 
  • @IBInspectable allows flagging certain variables to be configured and shown in IB. 

Debugging Overview

  • XCode 6 shows how the block got into the stack queue.  In the stack trace that looks like: "Enqueued from com.apple.uikit...." 
  • If you are developing an App Extension, XCode automatically attaches the debugger to your extension when you bring up the notification centre on the device. 
  • New debug instrumentation guages for finding problems in File and Network IO. 
  • View Debugger allows inspecting the view hierarchy to understand why things don't look in the expected fashion.

Performance Overview

  • Instruments has a new UI. 
  • XCode Server gets Trigger support that gives custom behavior to your CI bots.  (Run command line scripts After integration step occurs).  Can run "On Success", "On Test Failures" or "On Build Errors".  
  • Performance test support added to the XCTest framework.   Wrap your code in [self measureBlock:^{ //your code }];     XCode will tell you if the speed of your code has improved or regressed.  
  • "Profile" option from the context menu when right clicking on the test itself allows regenerating profiles for individual tests. 
  • New report that summarizes performance tests. 


Swift Demo (Daniel Dunbar)

  • Module names can now be specified for classes in Interface builder.  So you can use short class names, and avoid naming collisions by using different modules. 
  • Can now define our own modules in our own frameworks, and use them in both Swift and Objective-C.   For example you can put all model code into a "Core" type of module.
  • In Swift, you no longer need to manually import individual headers from a module.  Just import the module itself, and all the public classes will be accessible.   
  • You will get inline auto-complete quick help docs even when using your own classes. 
  • Typed Collection support allows specifying a cast to a type, for example:  " as Game[]" so now the compiler knows that we are dealing with an array of Game objects going forward.
  • iOS8 has a new "separatorEffect" visual property for TableViews.  (Set to a UIVisualEffect)
  • Objective-C Headers are dynamically translated to the Swift syntax on-the-fly, preserving original API comments.
  • Automatic Type inferrence automatically finds the right enumeration type.  So you can just type things like:  .Dark, and it will know which enum to use based on parameter type.  
  • A Header is automatically generated for you in the format:  "ModuleName-Swift.h".   You can import this header into any Objective-C file in order to gain access to all Swift classes within that Module. 
  • Option+Double Click opens Quick Help for any Symbol or Build Setting.  Quick help works across Swift and Objective-C. 

Interface Builder Demo (Jon Hess)

  • Playground shows you values of variables on the right.  Press + on any of the inspected variables in the right pane to bring up a persistent preview of any variable.  Results update immediately as you change the code. 
  • Desaturation effect example:  UIColor(white: 1.0, alpha: 1.0 - 0.3).set()  
  • Option + Click to open any resource in the assistant.  Such as the storyboard. 
  • @IBDesignable indicates that your object should be of specified type at Design type, not just at Run Time.  So in IB, your class will be executed by Interface builder, and look as you intended it to according to your code-behind. 
  • override func prepareForInterfaceBuilder() {  }   can be overridden to make sure that the view is set up to properly show up in IB.  Set up a default image here, or anything you need to do. 
  • @IBInspectable can be applied on member variables, which exposes them as fields in IB that can be set. 
  • In IB you can click on a View, then go "Debug Selected Views", and the related code to draw that View will be called, allowing you to debug into it without running your project from scratch.   
  • New Feature: Universal Storyboards allows to target to both the iPad and iPhone.  To enable:  click on your storyboard, and in the File inspector, enable:  "Use Size Classes". 
  • You can specify which constraints participate for which size classes.
  • You can specify what segues do based on size class.  (For example:  Popover on the iPad, and a Modal on the iPhone). 
  • Preview tool allows viewing how your app will look on multiple screen sizes at the same time.  To activate:  Open the "Enhanced Preview Editor", and select" Preview: Main_iPhone.storyboard, for example.  Then on the bottom press + to add additional device types to the same preview screen. 
  • Size classes can be selected from IB's bottom Bar, that defaults to "Any".  Choose "Regular" to work with the largest size class (iPad).  The bottom bar will turn blue, to remind you that you are editing the design for a specific size class. 
  • Any changes done in IB when selecting a specific size class will only be applied to that size class. 
  • New Aspect Ratio constraint allows to pin the relationship between width and height. 

Debugger Demo (Ken Orr)

  • You can now mouse-over a UIView in the code, and click the QuickLook Icon to see a rendering of that view, to make sure that you are in the right place in the code.  Also works for Mac apps for NSView.
  • - (id) debugQuickLookObject is a new method you can implement on any of your classes.  It will be called by XCode when you initiate QuickLook from the debugger.
  • New "Debug View Hierarchy" button on the bottom.  Shows view snapshots, frames and a visual representation of your views.   Allows inspecting object types and their properties at run time.  
  • When you click on a view in the "Debug View Hierarchy" view, you can also navigate the "Bread-Crumb" on top to see how the view is embedded, and who owns it.  Now you know which area in the code is responsible for drawing any given view you're seeing, without having to guess. 
  • Twist the view sideways in the View Debugger.  
  • The Left slider allows separating views in the hierarchy further.
  • The Right slider allows hiding view from the front to the back, exposing underlying views. 
  • "Show Constraints" button hides all other views, and only shows you the view you selected, and its' constraints. 

Performance Demo (Kate Stone)

  • extension is a new Swift feature (Similar to category), which allows adding methods to a class. 
  • Example:  New File --> Test Case Class --> PerfTests. 
    • By default will contain the following methods:  setUp(), tearDown(), testExample(), testPerformanceExample()
  • testPerformanceExample() contains measureBlock { ... } by default. 
  • Performance test runs a few times to find an average run timing, and consistency of run-to-run timing.  
  • Mouse over the "No baseline..." warning after running the test.  And fill in the Baseline values to establish a baseline for the test. 
  • Right click the test --> "Profile", to launch instruments to profile that specific test only. 
  • Instruments doesn't immediately record anymore.  You can first change the settings now, before you start recording. 
  • Click and drag in the memory chart to filter a range of allocations in the timeline. 
  • Stack trees view in instruments shows a statistical breakdown of allocations by object type. 
  • XCode server gives a dashboard report of tests over time, success/failure history, and device specific results. 

LLVM Compiler - New Features (August 2014)

Here are some notable points from WWDC 2014 "What's new in LLVM" (August, 2014):

  1. 64-Bit iOS Support.  In XCode 6, the "Standard Architectures" build setting now builds for 64 bit architectures by default.    

  2. arm64 is an entirely new architecture.  So the entire application needs to be built for 64 bit support, including all libraries you depend on.  If you use a lot of libraries, you need to work with your vendors to obtain 64 bit versions. 

  3. "Migration Hints" include: Function type checking, Objective-C Bool type, Type size independence.

  4. C Function calls now must have prototypes defined, prior to calling the function. If a call to a C function is made for which no prototype has been defined, the following error results:  "implicit declaration of function 'other_function' is invalid in C99"

  5. New project setting: "Enable Strict Checking of objc_msgSend Calls" = YES is a recommended setting that enforces you to have strict type checking every time objc_msgSend is used.  The proper way to use objc_msgSend is: 

      • typedef void (*send_type)(void *, SEL, int); 
      • send_type func = (send_type)objc_msgSend;
      • func(object, sel_getUid("foo:"), 5);  
    This is done to let the compiler know what the final receiving type is.  (For optimization purposes)

  6. New Objective-C Boolean Type.   Previously, in 32-bit iOS, a bool is a Signed Character.  Now it's a new type:  BOOL ("_Bool").   If boolean variables were having non-boolean values put into them (such as a -1), the result of the calculation with those values will be different between 32-bit and 64-bit architectures.  This is something to watch out for. 

  7. Pointers are now also 64-bit.  So if we have places in the code that cast from a smaller integer type to a new 64-bit pointer, we now get a compiler warning:  "cast to 'void *' from smaller integer type 'int'  for a piece of code like this:   return (void*)i;   (where i is an int).   

  8. The C language typedefs should be used to address this:   
    1. intptr_t, uintptr_t for saving pointers to integers.    
    2. size_t for array indeces.   
    3. ptrdiff_t for pointer differences.   

  9. The long type is 4 bytes on 32-bit iOS, and is 8-bytes in 64-bit iOS. 

  10. Objective-C Modernization Tool:  Scans older legacy code to identify opportunities to use new features that adopt best practices.   Accessible from "Edit --> Refactor --> Modernize...".   Select which targets to modernize.   Then you select what Options to modernise.  It's a good idea to go 1 option at a time, in order to make it more manageable. 
    1. Add attribute annotations: Adds annotations such as: NS_RETURNS_INNER_POINTER 
    2. Atomicity of inferred properties: Scans your classes for getter/setter methods that should be instead encased in properties, and converts them to properties, adding appropriate Interface definition, such as:
    3. - (NSString *)name; 
      - (void)setName:(NSString *)newName; 
      Will be replaced by: 
       @property (nonatomic, copy) NSString *name;
    1. Infer designated initializer methods: Allows you to tell the compiler which is the main designated initializer for the class. This Option scans all your classes, finds and marks your designated initializers for you.  Example:  - (instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER;
    2. Infer instancetype for method result type:   Makes our initializers more strongly typed.  You get increased type safety.  For explanation, visit:  http://nshipster.com/instancetype/
    3. Infer protocol conformance: Scans classes and finds if all required methods of a particular protocol are implemented.  If they are, then it will add the protocol conformance line in the Header file.   More descriptive and maintainable. 
    4. Infer readonly properties:  Scans for properties which are only read, and puts the "readonly" modifier on them to make that more explicit. 
    5. Infer readwrite properties
    6. ObjC literals: Shortens your code, replacing things like: [NSNumber numberWithInteger:42] with @42 
    7. ObjC subscripting
    8. Only modify public headers
    9. Use NS_ENUM/NS_OPTIONS macros:  New style Enum macroes that specify the type and size to the compiler.  For example: 
    10. typedef  NS_ENUM(NSInteger, UYLType) 

       UYLTypeDefault, 
       UYLTypeSmall, 
       UYLTypeLarge 
      };

  11. User-Defined Modules:  modern alternatives to precompiled headers, which are more fragile.  They also give you:  Fast Compilation, Clear Semantics and Swift Interoperability. 
    1. You can only have 1 pre-compiled header at a time. 
    2. Precompiled headers are fragile because they can be included more than once in a single compilation, or DEFINEs interfering with each other, messing up the inner workings of the imported framework.  for example:  #define count 100 can break your imported libraries by messing up their internal logic. 
    3. Modules are "semantic import", not "textual inclusion", therefore not fragile. 
    4. To define a module, go to the "Packaging" grouping in your XCode build settings, set "Defines Module" to Yes. 
    5. To import a module:   @import ModuleName;  (Import into another target)
    6. #import <ModuleName/ModuleName.h>  (The compiler is smart enough to realize if the framework being imported is modular, and perform an implicit import, rather than a textual one.  But it's good to update to use @import instead to remove ambiguity). 
    7. Do not expose non-modular imports, such as  #import "Postgres.h", in your API headers. Only do textual imports in the implementation. 
    8. You can still define a Macro on the Command line or in XCode build settings, such as:  "-DDEBUG=1" if you want to affect frameworks which are modular.  (Instead of doing:  "#define DEBUG 1" in the source the old way.)

  12. PGO (Profile Guided Optimization) 
    1. Without optimization, compiler assumes that all inputs to your code are equally likely.  It can't know the most used code paths in order to profile the code.  This feature allows providing a profile to the compiler in order to optimize the execution based on the most-used scenario.  This can result in up to %20 performance boost while running your app. 
    2. An "Instrumented App" is generated as a profile, and specified in your project settings, to guide the compiler to optimize your app for that specific profile.  Optimizations include: 
      1. "Inline more aggressively for 'hot' functions", 
      2. "Lay out most common common code paths contiguously"
      3. "Better register allocation"
      4. Other
    3. To collect a profile:  Product --> Perform Action --> "Generate Optimization Profile" command.  Important to exercise all of the performance-oriented code.  (If you have a game with 3 levels, make sure to play all the levels).  
    4. Build with PGO:   Project Build Settings:  "Use Optimization Profile": "Yes" for the release configuration. 
    5. You have to update your profile after you changed the code quite a bit, because you gradually lose the optimization level.  "Out of date" profile warnings will pop up over time, as you change your code.  
    6. Can use Performance tests to drive the profiling.  But the performance tests should be realistic to how users use your app. 

  13. Vectorization in LLVM
    1. Loop vectorization is a compiler optimization that accelerates loops by providing vector hints to the compiler.  Temp vector variables are used to process more of the workload in parallel. 
    2. Now Analysis of complicated loops have been improved.  More loops can now be vectorized.  Loop vectorizer works together with PGO to make better decisions. 
    3. Improved ARM64 and X86 code generation:  Vectorizer understands the underlying process architecture. ,  Generate better optimized code sequences. 
    4. Specialization of loop values:   Creates a second vectorized version of your loop in which required variables are assumed to allow continuous memory access.  Vectorization is applied to it as normal, and the optimized version of the loop is used if that variable condition is true.  Otherwise, the regular optimized version of the loop is used. 
    5. New kind of vectorizer:  SLP Vectorizer.  (Superworld Level Parallelism:  Parallelism beyond loops).   Glues multiple scalars in your code into vector instructions.   Processes multiple scalars at the same time instead of sequentially.  (Speeds up numerically complex applications). 
    6. In XCode 6: Loop and SLP vectorizers are enabled by default in Release mode. 

  14. Acceleration of Javascript Code.  
    1. WebKit is the heart of the Safari web browser.  
    2. Interpreter executes javascript. 
    3. Two JITs (just in time compilers) accelerate JavaScript.   
    4. Interpreter --> Fast JIT --> Optimizing JIT  --> LLVM JIT (new)
    5. There are trade-offs between quality of code and time spent in the compiler. 
    6. Now LLVM is added to the chain to optimize functions which are run thousands of times.   (Heavy Games for example ported to JavaScript from C++, such as Quake 3)
    7. Javascript is dynamically typed.  WebKit uses statistical evidence of the type used previously and optimize for that type.   Then checks are added to prevent overflows by making assumptions and verifying them.  If the assumptions are broken, fall back to the regular interpreter.  (Only it can handle extreme cases, when type actually changes) 
    8. "On-stack replacement" migrates the state of the program from LLVM back to WebKit, and continue execution in the interpreter. 
    9. Compiling with LLVM is very beneficial for math-intensive applications. 
    10. OS10 and iOS on both 32bit and 64 bit now use LLVM in safari. 
Learn how to create your own Programming Language here!!

The Mobile Startup: Episode 5: Some thoughts about tech, and work.

Knowing that You're Bad! I think that if you have never thought of yourself as a bad engineer before, then you are probably a Bad e...