Thoughts about React Native after a few months working with it

 

react-native-800x450.png

I faced the following challenge in January:

  • Porting a complex webapp¬†to native Android and iOS. The web-app to be ported is written in ReactJs+Redux. Besides most of its business logic is in a pure ES5 javascript library.

So in this situation, React Native¬†(“RN” from now on) seemed like the way to go as we wanted to have a working prototype in a month and it should be maintained in both Android and iOS without extra resources.

Misconceptions

Some misconceptions(?) about RN that I’ll talk about:

  1. RN is a solution for pure developers who only want to know a bit about mobile native development. (FALSE)
  2. RN means learn¬†‘once’¬† and write anywhere (yes but…)
  3. RN might not make sense if you are a proficient mobile native developer (FALSE)
  4. RN in the worst case can perform too badly to the point of having to rewrite everything to native when it’s too late. (FALSE)
  5. RN allows to reuse tons of code among platform (TRUE)
  6. RN is fun (TRUE!)

Let’s divide and conquer the discussion:

Tooling

react-native run-platform little disappointment

I’ll avoid talking about Expo as I cannot rely on it because I use a few native libraries that require the app to be ejected. So, the first experience creating a RN app is pretty cool, you just do react native init MyNewFancyApp¬†and there you have a hello world which you can run with react-native run-PLATFORM

Do both react-native run-android / run-ios work as you would expect? Well, more-less:

  • react-native run-ios¬†compiles your¬†iOS project, including native dependencies, links the project and runs Metro so that the JS code is bundled and offered by a Node server running on your laptop. Finally it runs your app in a Simulator target.
  • react-native run-android compiles your¬†Android app with Gradle¬†and also runs Metro the same way but there’s a¬†difference: it won’t start an emulator or simulator, it will try to run adb install against whatever is attached to your laptop: an emulator running in Genymotion, a real device connected to USB…
Captura de pantalla 2018-05-18 a las 20.36.31
You get used to keep an eye on this.

This is the first little difference you find between using RN against each platform and this is just about tooling. react-native run-PLATFORM has different behaviour¬†on Android and iOS. Actually, if you want to run your¬†RN app in your device react-native run-android will work fine as “adb install” works both for emulator and devices the same way whereas react-native run-ios is only enough for running on the simulator. You’ll need to run Xcode to run it in your device. You might think “not a big deal” and you’re right but it turns out RN is full of this kind of details that could be improved and make dev experience better.

Captura de pantalla 2018-05-18 a las 20.38.04
My 2 IDE friends always opened for RN work

 

A RN app is a native app so you’ll need to learn mobile native stuff

You’ll see react-native init basically creates a Gradle¬†Java android project under /android folde,¬†a /iOS project under ios folder and a /index.js¬†to start the RN app.

You might think you won’t need to care about those autogenerated¬†native projects and just about the JS and you’ll be wrong.

Every time you link a npm¬†RN library containing native code (with react-native link) you’ll see how it patches your projects, and sometimes it won’t be enough and you’ll need to do some manual changes to integrate such libraries correctly. This means you cannot be a 0 native knowledge developer to use RN, you’ll need to get your¬†hands on¬†those native projects from time to time. Don’t cry about it, embrace it as this will rarely change as RN is basically about patching those native projects that you scaffold initially over and over again and you’d better check what changes you introduce “automatically” when you link new libraries. It’s a good practice trying to understand the generated patch every time you run react-native link¬†.

Does this mean you need to know both Java and Objective-C to be as productive RN developer? IMHO Yes.

 

41qQV3hJhNL._SX348_BO1,204,203,200_
I enjoyed this book.

 

For Java there are plenty of books you can use whereas for learning Objective-C I can recommend Objective-C Programming: The Big Nerd Ranch Guide (Big Nerd Ranch Guides) 1st Edition.

You can also learn Swift but you’ll see that you need to learn Objective-C anyway so that should be your priority as most of RN libs are written in Objective-C and your /ios RN generated project is in Objective-C.

There are other examples that enforce the idea that if you want to do serious RN job and you only know Javascript you really should learn mobile native languages anyway is that there are simple things such as changing the background of your app or¬†tweaking the splash screen¬†that you simply cannot perform just with Javascript. These are more exceptions than the general rule but you don’t want to limit yourself anyway.

I can mention that you probably need to change AppDelegate.m when using certain libraries, and those libraries typically have some code you can copy-paste there but they don’t tell you how to mix different libraries there correctly, that’s something you need to do with care and at least some Objective-C understanding. E.g some libs tells you to add a continueUserActivity method in AppDelegate.m which can collide with other libraries you had and you might need to figure out yourself.

Captura de pantalla 2018-05-19 a las 11.49.45
Just a simple example of supporting 2 libraries at the same time

At some point, you might even need to create a native module yourself. RN documentation documents two examples about how to do it so you can see that the vision of RN is not about avoiding any native development, it’s more about boosting productivity and sharing business logic and practices among very different platforms.

Debug mode and runtimes

Usually, when you’re developing with RN you will be using DEBUG mode. You’ll soon discover that running your app that way means that your JS code is being run by your laptop browser which is important to have in mind as in Android especially you can hit important differences that will make you introduce extra polyfills. E.g Symbol._iterator issue.

My advice for this is clear: test your JS code often in your device/simulator, don’t live in the browser runtime all the time until a bad surprise comes too late when you thought your code was already ready. You might think, Tests!: well, that kind of problems will be detected if your running those tests with the device runtime, otherwise won’t be detected either ūüė¶

In practice, I’m usually developing with both Chrome and an iOS device runtime and I check from time to time on Android and It’s common finding a surprise to fix. It also depends on which is your prioritized platform, in my case I focus on iOS first and I care about nailing Android with less priority. You cannot assume things just will work in every platform out of the box.

Testing

Captura de pantalla 2018-05-19 a las 2.10.16.png
from https://speakerdeck.com/frantic/react-native-under-the-hood

Testing in native platforms is quite mature so I was not sure about whether I would be comfortable with RN in that regard. Luckily it’s pretty good, it takes some time to get used to the way dependency injection is done (basically ES6 imports and props) but Jest testing framework rocks and storybooks + snapshots is pretty cool. Besides, as Redux is the de facto standard to develop RN apps that’s a part which is testable by default as it enforces using pure functions. Perhaps I miss that in RN world is common seeing native libraries with no test coverage at all, my recommendation is checking the project README and the issues first as a project that seems great at first glance might be better to avoid for not being maintained or being buggy. You’ll find there are lots of react-native-foo libs that expose “foo” native APIs but the quality among them is different and there are different libraries doing the same thing with different level of quality.

Organizing your code

About organizing your code, don’t assume you should do it the way you see in basic examples, consider them just a starting point to having something working but not something maintainable in long-term. E.g avoid adding all your business logic directly to your components, favour pure functions (using Redux is a must), extract redux part from component to containers, find a consistent way to organize your styles instead of just having them spread in your components and in general apply any practice you know from other good languages/frameworks even if you rarely see them in common RN examples.

One more thing: sometimes you’ll find you need different code depending on platforms, think carefully about how to do it as the typical “if(platform == ‘ios’)” can be a first working approach but you should try to wrap those blocks in generic classes or components which deal with the differences internally so that you don’t have lots of platform branching in your main business logic.

Preparing builds

1_txtcYocQEGtOFN33ZCTDbw.png

Preparing release/alpha RN builds is as complex or even a bit more than preparing classic native ones as you also need to care about the JS bundle. Luckily you can automate with fastlane, something you should really do to avoid the pain of preparing them manually. Besides you can consider using Codepush so that you can avoid preparing new builds unless you’ve really changed native dependencies.

Performance

This was one of my main doubts about RN:

  1. Most of your code is in JS and Javascript code does not run in UI thread, it has its own background thread. This is great for someone used to Android development where that’s a typical problem when running your code. In RN if you have bad performance because of your JS code you won’t be affecting UI thread as JS runs in a different thread. Besides the async nature of running your JS code makes deadlocks unlikely, something that I’ve seen happening in Android depending on the practices.
  2. Performance issues are quite easy to detect thanks to libraries like slowlog and snoppy. With slowlog you can monitor whether components take too much time to mount and with snoppy you can watch whether you’re having excessive activity in the RN bridge.
  3. There are lots of little easy details to care of like disabling console logs for production, typically avoid blocking JS event loop, profiling your app performance.. You can read more about them in this nice documentation.
  4. Just avoid doing animations with the Javascript thread, search for native libraries that can help and useNativeDriver flag in animations.

 

The RN bridge

 

Captura de pantalla 2018-05-19 a las 2.12.28
from https://speakerdeck.com/frantic/react-native-under-the-hood

RN bridge is an important thing to understand as RN developer. Magic does not exist, in RN either. Your JS code runs in a background thread and your native modules run on their own background threads too so how does your JS code communicate with your native modules?

How is a call from javascript translated to native land?

Well, basically the message object you want to send to the native API that will send the message is serialized so that it can be communicated to the other thread, and then it’s unserialized in the native thread side. That’s basically the bridge and it has a cost. If you are doing too many communication from JS to Native or vice-versa that will degrade your app, those calls are actually batched but It can become a problem anyway. That’s a bottleneck as other code that needs the bridge to run will need to wait.

How can you take care about this? As I said you can use a tool like snoppy to monitor it. If you rarely see high peaks in such bridge, congratulations! You’re achieving native-like performance in your react-native app. Otherwise, you’ll need to do something about it. What? Well, if those peaks are quite rare you can try to improve the UX when they happen… whereas if they really affect the user experience or battery you might need to port some JS code to a native module because that’s something to take into account.

Pure JS libs vs RN native libs

Related to this you’ll often find different libraries that try to do the same thing but one does it in Javascript (always using JS thread) whereas the other one requires adding native code to your android/ios native projects. The pure JS library is probably easier to set up whereas the one including native code will require a react-native link in the best case (+checking the patch carefully) but It can also happen that you need to use Cocoapods and you might need to apply some monkey patches yourself. You need to evaluate each case because such “pain” might pay off. An example of this is choosing a navigation lib for your RN app, I prefer react-native-navigation to react-navigation.

A kind of magic

maxresdefault

It can be interesting checking the RN repo to see the magic under the hood.

E.g: In BatchedBridge/MessageQueue.js you can see the enqueueNativeCall method:

Captura de pantalla 2018-05-19 a las 2.52.52.png

In that method, you’ll see method and params data are pushed to _queue and that queue is flushed from time to time.¬†calling¬† global.nativeFlushQueueImmediate(queue). And what’s next step? If you look for nativeFkushQueueImmediate you’ll see you land into C++ world and you can see the interesting part where the queue is JSON serialized. From there you go NativeToJsBridge.cpp where you can see the implementation of both JsToNativeBridge and NativeToJsBridge. CallNativeMethod is finally run in ModuleRegistry.cpp¬†and after that you’re already in platform specific area, e.g you can see the actual call being performed with reflection in JavaModuleWrapper.java¬†whereas I think that job is done in RTCNativeModule.mm for iOS.

 

Fun ūüôā

Captura de pantalla 2018-05-19 a las 3.47.45.png

So why RN can be more enjoyable for a native developer?

Basically because you rarely need to recompile your app unless you change the native dependencies, something that you’re not doing N times a day and not even N times a week probably whereas you’re probably changing templates N times a day, or business logic, or assets, or colours… And those things in RN are in JS and you can just refresh and see the changes almost instantly! This makes RN development cycle way more similar to web development as the feedback cycle is way-way faster and you can be way more time in the zone having fun as a happy developer as you don’t need to be multitasking to find other little things to do at the same time your app is being rebuilt, even if your app is small and just takes like 30 seconds to rebuild that’s still way more than what JS code takes to be loaded again. You can even enable hot reloading! and you’ll see how your app changes as you change JS lines.

In Summary

So, when do I think react-native is a good idea as of today? IMHO it worths seriously considering if:

  • You need to port a web app written in ReactJS+Redux to Android/IOS which is quite complex and just runs fine.
  • You want to prototype a native app fast. I avoided talking about Expo but check it out, if you’re lucky and you can use it it can be a good extra developer performance boost.

And when do I think it might not pay off?:

  • You have enough amount and good mobile native developers to develop the app for each platform.
  • You already have solid native apps for each platform, rewriting them to RN might not make sense unless you want to reuse web version business logic.

march-simply-supply-recruitment-misconceptions

And lastly, let’s review the misconceptions I talked about at the beginning:

  • RN is a solution for pure developers who only want to know a bit about mobile native development.
    • FALSE: you need to understand those android and iOS folders, you need to be able to install RN libs including native code and you even might need to write your own native modules!
  • RN means learn¬†‘once’¬† and write anywhere.
    • Yes but…¬†you¬†need to learn as much as you can for each specific platform.
  • RN might not make sense if you are a proficient mobile native developer.
    • FALSE: productivity can be quite bigger in RN.
  • RN in the worst case can perform too badly to the point of having to rewrite everything to native when it’s too late.
    • FALSE: in the worst case you can migrate JS code to native code.
  • RN allows reusing tons of code among platform.
    • TRUE: In the app I built, the whole redux code is the same in RN and ReactJs and that’s where most of the complex business logic is. Besides code differences between Android and iOS are just some UI details here and there to improve the experience for each platform.
  • RN is fun.
    • TRUE!: See the minion “Fun” part ūüôā

I hope this blog post can serve others introducing to this framework which is nice and powerful but there are a few things to consider or it’s easy to be disappointed.

Advertisements

A Tech Lead HOWTO

I’ve been working in a Tech Lead role position for something more than 2.5 years. Some notes I can write here that would have been useful for me and hopefully for someone reaching this page:

  1. Read this HN question comments: https://news.ycombinator.com/item?id=10395046
  2. Create a roadmap, parallel to the team projects. Make sure you have a long-term plan in mind.Having-a-Social-Media-Game-Plan-Higher-Profits.jpg
  3. Your team needs to fulfill the projects maintaining¬†a good working environment, otherwise, they’ll burn out soon. The opposite is true too, it does matter having the happiest team if projects don’t evolve as they should.Happy_minions.jpg
  4. Be patient, start just with little improvements as you understand your area. Avoid revolution feeling, people don’t like too many changes at the same time.
  5. Coding is probably not¬†the most important thing you’ll do for your team. First months it will feel awkward but you’ll get used to it once you understand your responsibilities.
  6. Understand your area top-down, from architecture to code so you’ll probably won’t be an expert in every repo but you probably should be an expert of how everything glues together, how the architecture works and how it should evolve.
  7. 1:1s are one of the most important things you’ll do, make sure most of the 1:1 time is just informal, the projects sync part should be just the first 5 minutes. Try fixing calendar events for them.1-1s.png
  8. Overcommunicate: tell important things to the team as a group and repeat it again in each 1:1 and see if your message is being understood. Always ask for the opinion, especially in 1:1s, your mates will often help you to do things better.
  9. Be data driven, make sure you can see the state of everything with data, you should not need to do ad-hoc queries or launching dirty scripts to gather important health data. Your important telemetrics and KPIs should always be available to be reviewed. However, if you find yourself checking a metric a lot for certain thresholds, just create an alarm!Data-driven-business.jpg
  10. You’ll need to keep caring about your craftsmanship and it will be more difficult than ever as you won’t be coding most of the day. However, you should make sure you keep improving technically, not just growing in soft skills. Try maintaining¬†pet-projects, courses and try to contribute¬†to team code in small priority tasks from time to time.
  11. Be involved in code reviews and read every pull request if possible, that’s where you’ll feel how good work is evolving. However, avoid micro-manage, especially to senior mates, just be a helpful safety net if needed. Avoid commenting in CRs if you have nothing important to say, avoid the “here comes the boss comment” syndrome.03
  12. Detect any block and tackle it with most urgency. It’s one of your main responsibilities. Ask for blocks in every standup.
  13. Be the tech proxy for your team so that they can focus on their tasks. Be ready to be interrupted, learn how to optimize context changes. Actually, make sure your team understands you’re approachable and they can ping you if any problem without waiting, you’re there to be interrupted at any time if needed.
  14. Supervise estimations. Avoid being always dummy conservative, think carefully about risks and if any high risk¬†then yes, be conservative with estimation. But if you’re estimating a task your team already did in the past, it should be pretty straightforward (and perhaps should be automated?)
  15. Try introducing and welcome changes to how things are done but be careful about when those changes are applied as if they impact a project, it can be difficult to justify. Related to this, avoid taking the easy route of just saying always “NO” to new things just to avoid risks, as your platform should evolve as part of your plan.main-qimg-fbef4b8b75dbb14bf216652c98ef2232
  16. Measure technical debt, buy it consciously and fight it as part of your plan with priorities.
  17. Improve your soft skills. You’ll be more time talking to people than to your IDE.
  18. Be always constructive with feedback, as a criticism without action points to follow is not a solution.
  19. Be the Toxic-comments goalkeeper. Try favoring a positive environment. However, don’t confuse toxic comment with a constructive critic.24293_1.jpg
  20. Tech Lead position is quite prone to workaholism. Go home! Read this post by Rafael López: https://badoo.com/techblog/blog/2017/04/11/leads-go-home-and-take-your-reports-with-you/

 

Good luck!

An easy Vim IDE setup: using Vundle

Are you bored of messing up with your own custom .vimrc which is eventually broken or difficult to maintain?. Well, there are lots of projects in order to have a vim plugin environment well setup, I’ll just show one of them. I’m following the steps you can see in https://github.com/jez/vim-as-an-ide install instructions:

  1. First, let’s get Vundle:
mv ~/.vim ~/.vim.beforeVundleBackup
mv ~/.vimrc ~/.vimrc.beforeVundleBackup
mkdir ~/.vim && mkdir ~/.vim/bundle/
git clone https://github.com/gmarik/Vundle.vim ~/.vim/bundle/Vundle.vim

With that, you already have the bare minimum to work with Vundle.

       2. Follow this to get a proper font: https://github.com/jez/vim-as-an-ide/commit/457f2e2

If your using iTerm2 basically you need to download the solarized.zip file and load preset from the iterm2-color-solarized folder.

Captura de pantalla 2017-05-27 a las 8.42.20.png

Import both: ‚ÄúSolarized Dark‚ÄĚ and ‚ÄúSolarized Light‚ÄĚ and you can decide later which one is more convenient.

In iTerm2 make sure this is your terminal type (more info):

Captura de pantalla 2017-05-27 a las 9.07.01.png

     3. Now it’s time to get the vimrc:

wget https://github.com/jez/vim-as-an-ide/raw/master/vimrc.vim && mv vimrc.vim ~/.vimrc

     4. Now runvim +PluginInstall +qall

And that’s all, now your Vim should look like this:

Captura de pantalla 2017-05-27 a las 9.10.37

Now you already have a pretty good vim setup and you’ll be able to install new plugins easier.

e.g I can install a SML plugin just adding this to the .vimrc:

Just remember to run this every time you run a plugin:

vim +PluginInstall +qall

Implication, conditional, equivalence and biconditional: NL and code

This blog post is my attempt to explain these topics: implication, conditional, equivalence and biconditional.

I’ll also try to discuss examples both in natural language and code.

I’ve studied them in¬†Mathematical Language subject and Introduction to Mathematical Thinking.

Implication

In natural language we often hear expressions or statements like this one:

If Athletic Bilbao wins, I’ll take a beer

Continue reading Implication, conditional, equivalence and biconditional: NL and code

Forks: wsdl2html_ivmos y wallahack_ivmos

25406

English

¬ŅQu√© hacer si tus pull requests no son aceptadas pero no quieres que esas aportaciones queden perdidas en ramas de tu fork? En mi opini√≥n, para eso precisamente son los forks y es una de las ventajas del software libre. Lo suyo es probar primero una pull request, tratar de aportar al proyecto, es lo m√°s pr√°ctico ya que el coste de mantener tu propio fork es considerable. Sin embargo a veces no es posible hacer que tus cambios lleguen al proyecto original y¬†las razones pueden ser varias. Es algo que me ha ocurrido recientemente con dos pull requests:

https://github.com/ivmos/wsdl2html_ivmos

ūüĎć

Esta pull request entre otras cosas a√Īade soporte a la utilidad wsdl2html para que se pueda autogenerar documentaci√≥n en html a partir del proyecto. En este caso entiendo perfectamente porqu√© la pull request no se acept√≥. Mi aproximaci√≥n es muy espec√≠fica para el caso de uso que me interesa: generar comentarios de un proyecto Java en el cual el WSDL se genera con JAX-WS en lugar de escribirse directamente. Genero los comentarios a partir de esos ficheros Java, lo cual es no es una forma √ļtil si trabajas directamente con el WSDL.

https://github.com/ivmos/wallahack_ivmos

ūüėě

Esta otra pull request sin embargo es bastante más triste. Sencillamente el autor nunca me contestó. Extendí la utilidad Wallahack, que permite consultar Wallapop haciendo scrapping de forma que puedes escribir scripts que busquen resultados periódicamente. Por ejemplo usé este fork durante un tiempo para detectar anuncios nuevos de ordenadores antiguos. La diferencia principal entre mi fork y el proyecto principal es que puede parametrizarse y tiene un par de arreglos que lo hacen usable.

En ambos casos no tengo suficiente tiempo ni interés para darles más evolución, por ello sigo la convención de renombrar sencillamente a {originalName}_ivmos.


Espa√Īol

What should I do if my pull request aren’t accepted and I don’t want those changes to be lost as branches in your fork? IMHO, that’s actually the reason forks make sense and a main advantage of open source. You should try a pull request, with the needed effort to make it successful as maintaining your own fork can quite a pain. However sometimes it’s not possible and your pull request is not accepted. That’s something I’ve seen at least 2 times I’m telling you about:

https://github.com/ivmos/wsdl2html_ivmos

ūüĎć

This pull request¬†is a branch which adds support to wsdl2html project. In this case I understand perfectly why the PR wasn’t accepted. My approach is very specific to the use case I had: generating comments from a java project where WSDL¬†was generated with JAX-WS instead of being written manually. I generate the comments from those java files, which is an approach that does not make sense if you have worked directly with the WSDL¬†(comments should be there).

https://github.com/ivmos/wallahack_ivmos

ūüėě

This other PR is sad though. It was simply never answered. I extended Wallahack, which is a java tool which queries Wallapop web so that you can write scripts that poll periodically for results. For example, I used it to check whether new old computers had been posted recently.

In both cases I don’t have time to invest more time on them, that’s why I follow the convention of renaming the forked project to {originalName}_ivmos instead of using a new fancy name.

Product Hunt Madrid | Tuenti & Fever | Campus Madrid

English

Product Hunt Madrid es un evento de descubrimiento y cr√≠tica de productos y servicios digitales. Los productos se presentar√°n desde tres perspectivas: las decisiones de dise√Īo tomadas, el stack tecnol√≥gico y el modelo de negocio. De esta forma la comunidad tecnol√≥gica de Madrid aprender√° c√≥mo funcionan los mejores productos digitales del mundo.

Hace una semana estuve contando lo que hacemos en Tuenti con mis compa√Īeros Laura Andina (UX) y Luis Javier √Ālvarez (Product).

Cont√© c√≥mo trabajamos los equipos de ingenier√≠a y algunas lecciones que hemos aprendido estos a√Īos.


Espa√Īol

Product Hunt Madrid is an event where Product Managers, Engineers and Designers show their products: how they’re built and how they build them. Products are presented from three views: key design decisions, tech stack and business model. This way Madrid community can learn from the experience of successful digital products.

One week ago I talked about Tuenti product with my mates Laura Andina (UX) and Luis Javier √Ālvarez (Product).

I talked about how we work in Engineering team and a few lessons we’ve learned these years.