Upload
konstantin-loginov
View
145
Download
8
Tags:
Embed Size (px)
Office Delve – for Office 365Konstantin Loginov
About me
• 7 years in Mobile development: Windows Mobile webOS Windows Phone 7/8 iOS (native/Xamarin) Android
Current Position: Software Engineer in Microsoft
LinkedIn / email
Office Delve
• “Flipboard for Office365” ©
• Code name: Oslo
• Tangled creation story
Steps towards Delve Mobile
Steps towards Delve Mobile
• Started as a team of two• Android first• Pivoted multiple times
& created various MVPs• Application as an engagement driver for
the whole service
Development
Working process
• Non-formal Scrum, 2-weeks-long sprint
• Bi-weekly releases
• Team Foundation Server 2013 for task tracking
• Slack for team collaboration (love it!)
• GIT as revision control system
• Android studio (latest Canary build) as an IDE
• Internal tool for bug-tracking and code reviews
• OneNote as a knowledge base
• Today: 4 Android devs & 3.5 iOS devs
We love opensource
• Dagger (dependency injection)
• ButterKnife (view injection)
• EventBus
• Retrofit
• OkHttp
• Picasso
• Esty StaggeredGridView
• Compatibility libs
Upcoming: Mortar & Flow. (As others, we Square )
• Mockito (Testing)
• AssertJ (Testing)
Design patterns we use
• Dependency injection
• Publish–subscribe pattern
• Data Access Object
Dependency Injection
Dependency Injection - Dagger
class DataProvider {
DataSource dataSource =
new DelveApi();
}
class DataProvider {
@Inject
DataSource dataSource;
}
11
class DataProvider {private DataSource dataSource;
@InjectDataProvider(DataSource dataSource) {
this.dataSource = dataSource;}
}
Dependency Injection - Dagger
• Standard javax.inject annotations (JSR-30)
• Need to declare “modules” for compile-time validation and code generation• Specifies “provider” methods
• @Singleton annotation
• Lists supported classes (which in turn generates code)
• Supports override• Inject mocks in tests
• Substituting back-ends is a one-line change
Dependency Injection - Dagger 2
• Just released
• No reflection, no ObjectGraph/Injector, @Component interface
• We’re planning to switch to it soon
Publish–subscribe pattern - EventBus
• We use greenrobot/EventBus
• Performs well with Activities, Fragments, and background threads
• Decouples event senders and receivers
• Avoids complex and error-prone dependencies and life cycle issues
Activity(hosts fragments)
Data Access Layer(Subscriber)
Fragment AFragment B
Data Subscriber
Error Subscriber
ERROR
Navigation Event Subscriber
Data Subscriber
Open Fragment A
Data Access Object• DAO is an object that provides an abstract interface to the database.
By mapping application calls to the persistence layer, DAO provides specific data operations without exposing details of the database.
User
User getById(String userId)List<User> queryMatch(String q, int l, int o)
SqlLocalStorageUserDao
User getById(String userId) {/* Getting data from SQLite */
}
List<User> queryMatch(String q,int l,int o) {/* Getting data from SQLite */
}
UserDaoImpl
DataProvider Layer
….localStorage.getUser(userId);….
UserDao userDao;
User getUser(String userId) {return userDao.getUserById(userId);
}
String userId;
Pinterest-style navigation model
• V1
Pros:
• Gestures between tabs
• Easy to implement
Cons:
• 3 «heavy» pages in ViewPager
• No Tab-switching-buttons in Profile/Document pages
Pinterest-style navigation model
• V2
Pros:• Still easy to implement• Pretty effective• Tab-buttons everywhere
Cons:• No gestures• Not keeping state of not-selected tab-fragments
Pinterest-style navigation model
• V3 (current)
Pros:
• Should be familiar for instagram users
Cons:
• Ugly in implementation
• Breaking OS design-guidelines
Pinterest-style navigation model – Going forward
• V4 (future)
Yeah! We like changes in Navigation model
• Side nav as the way of switching between pivots
• Material design
Testing
Testing
• Manual testing
• Alpha & Beta programs
• Unit tests (Test Coverage 75+%) Mockito
AssertJ
• Monkey testing( adb shell monkey -p com.microsoft.delvemobile -v 10000 )
• Memory profiling
Mockito
• Mocks made easy• Don’t “expect” before the fact; query object afterwards
• Simple to use
• Stages of a test• Setup (as necessary)
• Test
• Verification
38
Mockito: Verify Interactions
// mock creation
List mockedList = mock(List.class);
// using mock object; observe that it didn't throw any
// "unexpected interaction exception" exception
mockedList.add("one");
mockedList.clear();
// selective & explicit verification
verify(mockedList).add("one");
verify(mockedList).clear();
39
Mockito: Verify Interactions 2
verify(mockedList, times(2)).add("one");
verify(mockedList, atLeastOnce()).add("one");
verify(mockedList, never()).clear();
40
Mockito: Stub Method Calls
// you can mock concrete classes, not only interfaces
LinkedList mockedList = mock(LinkedList.class);
// stubbing; before the actual execution
when(mockedList.get(0)).thenReturn("first");
// the following prints "first"
System.out.println(mockedList.get(0));
// the following prints "null" because get(999) was not stubbed
System.out.println(mockedList.get(999));
41
Mockito: Advanced Features
• Spy: Partial stubbing of real object through proxy
• Mocking by annotation
• Argument matching
42
AssertJ: Readable Asserts
Regular JUnit
assertEquals(View.GONE,view.getVisibility());
AssertJ Android
assertThat(view).isGone();
43
public static final int GONE = 0x00000008;
AssertJ: Readable Assert Chaining
Regular JUnit
assertEquals(View.VISIBLE,layout.getVisibility());
assertEquals(VERTICAL,layout.getOrientation());
assertEquals(4,layout.getChildCount());
assertEquals(SHOW_DIVIDERS_MIDDLE,
layout.getShowDividers());
AssertJ Android
assertThat(layout)
.isVisible()
.isVertical()
.hasChildCount(4)
.hasShowDividers(
SHOW_DIVIDERS_MIDDLE);
44
Analytics & Crashalitics
We use (on both platforms):• Crittercism (http://www.crittercism.com/)
• MixPanel (https://mixpanel.com/)
• AppFigures (https://appfigures.com/)
Data reviewed daily
Crittercism
• Automated Crash logging
• Automated network request logging
• Breadcrumbs
• Handled exceptions logging
• Alarms & lifetime dashboard• latency
• error rate
• request volume
Crittercism: cases
• Delve Mobile crashed 44 times (14-26 April)
• Our crash rate:
• Average crash rate:
Crittercism: our crashes
• Most popular crash (50+% of total number):• Breadcrumbs we got:
MixPanel
• Funnels
• User-events
• Measure user’s retention & engagement
Feedback we got
Feedback we got through feedback-form:• Disabling notifications feature-request• Empty documents feed issues
Things we learn
• Cross-platform design does not work
• Square rocks
• Majority of our users are using Android 5.0+
• Learn about your users before start: majority of our users are using iOS (~1:3)
• Fragments are bad
• Crittercism is amazing