Mobile Development
The Agile Utopia
Woody Rousseau
Deputy CTO - Theodo UK
https://twitter.com/WoodyRousseau
https://github.com/wrousseau
Theodo
Helping our clients seize the opportunity of the digital transformation since 2009
Theodo
2009
2015
100
15
25
2014
2016
10
Succeeding a Project
Happy client
Succeeding a Project
Theodo Standards Met
Customer Satisfaction Implications
Super fast team of developers
Amazing user experience (UI, UX, 60 FPS)
Scrum
DevOps
Lean
The Web Development Utopia
Top engineers
PHP, Python and Javascript experts
The Web Development Utopia
Development Tools
The Web Development Utopia
Build Tools
The Web Development Utopia
Easy Deployment Process
Provision
Amazon EC2
Web App
The WebView approach
WebView
HTML
JS
CSS
Apache
Cordova
Write once, run everywhere
The Issues
- Performance issues: is 60fps reachable?
- Writing reusable code is hard
- No native look & feel
Our Current Stack
- React Native
- Fastlane
- Code-Push
The React Native Approach
React Code
+
Vendors
Going Fast
Reusability
Goal
Spend 0 time re-writing code
const Button = props => (
<TouchableOpacity onPress={props.onPress}>
<View style={styles.container}>
<Text bold style={styles.text}>{props.text}</Text>
</View>
</TouchableOpacity>
);
Button.propTypes = {
text: PropTypes.string.isRequired,
onPress: PropTypes.func,
};
React Component
const borderRadius = (Platform.OS === 'android') ? 5 : 0;
const Button = props => (
<TouchableOpacity onPress={props.onPress}>
<View style={[styles.container, { borderRadius }]}>
<Text bold style={styles.text}>{props.text}</Text>
</View>
</TouchableOpacity>
);
Button.propTypes = {
text: PropTypes.string.isRequired,
onPress: PropTypes.func,
};
React Component
const Button = props => (
<TouchableOpacity onPress={props.onPress}>
<View style={styles.container}>
<Text bold style={styles.text}>
{props.text}
</Text>
</View>
</TouchableOpacity>
);
Button.propTypes = {
text: PropTypes.string.isRequired,
onPress: PropTypes.func,
};
React Component
const Button = props => (
<TouchableHighlight onPress={props.onPress}>
<View style={styles.container}>
<Text bold style={styles.text}>
Button: {props.text}
</Text>
</View>
</TouchableHighlight>
);
Button.propTypes = {
text: PropTypes.string.isRequired,
onPress: PropTypes.func,
};
Button.ios.js
Button.android.js
<Button text="Wow" onPress={Actions.home} />
React Component
Using the component
Reusability
- 0 line of native code on my latest 8 weeks React Native project
- 8 uses of Platform.OS
- 2 cases of custom component (Tab and TabBar)
Productivity
Deployment
Goal
- Deploy fast
The Native Situation
1. Build with Gradle
2. Sign
The Native Situation
1. Create signing certificate
2. Create app id
3. Create push notification certificate
3. Set entitlements for the app id
4. Create a provisioning profile
5. Feed to XCode
6. Hope it works
Fastlane
platform :ios do
lane :deploy do |options|
if options[:env] == 'prod' then
sh('./update-pbxproj.sh')
end
match
gym
if options[:env] == 'staging' then
hockey
elsif options[:env] == 'prod' then
deliver
end
end
end
Apple
Developer
Git Repository
Encryption
Can I get this at home?
https://github.com/bamlab/generator-rn-toolbox
Testing
Quality
Speed
Tests
- Unit tests (state management)
- Shallow Rendering Testing
describe('<NavBar />', () => {
it('should get to a user profile when clicking', () => {
const wrapper = shallow((
<NavBar
rightComponentIcon="Profile"
rightComponentAction={() => Actions.profile({ userId: 2 })}
/>
));
expect(wrapper.find(TouchableOpacity)).to.have.length(1);
wrapper.find(TouchableOpacity).at(0).simulate('press');
expect(Actions.profile.calledWithExactly({
userId: 2,
})).to.be.true;
});
});
End to end testing
Phase 1 : The Honeymoon
End to end testing
Phase 2 : Mourning
1. Denial and isolation
2. Anger
3. Bargaining
4. Depression
5. Acceptance
End to end testing
If you want to give it a shot...
https://github.com/wix/detox
End to end testing
Otherwise: Snapshot testing
it('renders with a provided email and password', () => {
const store = mockStore({ credentials: Map({
email: 'myemail@gmail.com',
password: 'mypassword',
}) });
const tree = renderer.create(
<Provider store={store}>
<Login resetState={() => {}} />
</Provider>,
).toJSON();
expect(tree).toMatchSnapshot();
});
Super Deployment
How can we go even faster?
Let's mess with Apple
Let's mess with Apple
React Code
+
Vendors
Code Push
- Bypass Apple validation
- Multi-env deployment
- Progressive rollout
- ...
- Can't do "native changes"
Have we succeeded?
Weekly Deploy in Production
Client satisfaction through speed
Getting customer feedback
Thank You!
Woody Rousseau — Theodo UK
twitter.com/WoodyRousseau
github.com/wrousseau
Mobile utopia
By Woody Rousseau
Mobile utopia
- 643