Today we dive into technical tips for building thriving mobility services.
Optimize data sources and the map for poor performing devices
Not everyone carries the latest iPhone in his pocket. The more users your service attracts, the larger scale of devices you must support. Massive adoption is a goal of every mobility service, so optimization for older and weak devices is necessary. Also, if the app drains the whole battery before the user even returns the bike, scooter, or flying carpet, you're going to have a bad time.
Right, so what can you do to lower the hunger for computing power when you have tons of POIs, traffic overview, live public transport data, parking zones, and more to display? Render all of these only in the immediate surroundings of the user. There is no need to load the whole city when the user needs to see only a few nearest streets on the map. It's better to process only the close surroundings using the level of the zoom for a definition of an area that should be processed. Like this, you'll avoid crashes and lags, plus you'll remind yourself of good old games where the environment was rendered depending on the movement of the character.
OK, but what about those situations when the user zooms out and views the whole city? Should you flood him with hundreds of POIs? Not really. Aggregate everything you can. Group individual vehicles, group POIs of the same category and neighborhood, and lower the granularity of the displayed content. It will benefit the user because he'll stay on top and give weak silicon a break.
Don't drown in third-parties APIs
You can't create a successful mobility service without external data sources and additional services like real-time traffic data or public transport vehicles positions. Therefore establishing suitable API connections is a must. It shouldn't be difficult if both parties are technologically advanced and the API services are adequately defined and documented. However, implementation in the mobility field can be challenging because there is very little standardization in integrating services and data objects.
So how do you make external connections sustainable and efficient? Using the existing integration patterns such as Adapter or Facade (or any other that fits the situation) is a worthy approach. Third-party integration points also have to be deterministic even in case of errors and ensure the integrity of the transferred data. It brings clarity and order to the system and makes it scalable and maintainable.
Establishing a new connection is one thing but handling changes and updates is another. How do you ensure backward compatibility? How are you going to version the API? What's the difference between a major and a minor patch? Make sure you answer all these questions. The documentation must reflect each modification, and don't forget to communicate changes to the consumers before you launch them.
Looking for a pro-tip? Sometimes, we love to use API proxy. The proxy connects to the correct API versions, so you don't have to worry about that. It also helps you control the integration points and govern many aspects.
One more thing. You can't connect to third parties without sharing some of your data with them. Always stick to the golden rule – the lower amount of data you share, the better. Follow this principle even if it requires changes in the integration APIs.
Prepare for testing in the streets, not from behind the desk
Testing is a vital part of any software development, and it is particularly essential when it comes to building a mobility service. Why? Because your product interacts with the real world and a faulty implementation may leave users on the streets unable to return a scooter, bike, or whatever they have rented. And that's frustrating.
Additionally, testing from the comfy chair in your office won't do in the mobility field because you need to get up, and try out the actual service. Has the scooter unlocked as it should have? Is the bike shown in the right place on the map?
Think about the testing strategy from the beginning and act accordingly. Write down scenarios, what you want to test, and how. If you develop a routing algorithm, you need to verify the results. If you need to test a bike-sharing service, you need the actual bike to see how it performs. Sounds easy, but not everyone keeps in mind to have dedicated hardware for development and testing needs.
A few practical tips: How do you test a routing algorithm without running around the whole city? It is beneficial if your IoT server allows you to create virtual objects on the map. Faking GPS positions enable you to simulate different conditions and test even the most complex edge cases. Creating many testing accounts for different scenarios and contexts also makes sense. Complexity in mobility scenarios is enormous, and therefore, even the slightest difference can impact the test results.
Is automated testing the right way? Yes, in many scenarios, plus it will help you in the long term. An essential factor for successful automated testing is the app's source code. Developers should follow specific guidelines and the same design patterns to make automated testing possible.
Pay attention to error messages
Error @1242qwe#. Is this what you want your users to see while freezing outside, desperately wishing to rent your car? We don't think so. A whole bunch of things can go south when using mobility services. Technical issues; IoT server that should have opened the car doesn't respond; the payment gateway returns a time-out, etc. These are your errors, but also, the user can have a blocked or expired card, fail verification, or forget to tick a consent. It doesn't matter what goes wrong, but you need to let the user know. A generic error message doesn't help. It only confuses everyone. Remember that the user can solve many things himself. If you tell him that his card has expired, he'll add a new one. On the other hand, he'll quit if you show him something like "Error to display error."
How do you avoid vague error messages? Map all possible error states extensively, then aggregate them into meaningful messages and implement them.
Context of the error is also essential. It always sucks when the error happens in your system, but at least you know what happened and how to fix it. On the contrary, there are cases when you have no clue because some random, undocumented error from third-party API hits you. Usually, there is not much you can do except try to map and investigate errors in the testing phase and make third-party developers resolve and document errors correctly.
Separate payment and service consumption
You pay. You consume services. From the user's point of view, this is what we are all used to – receiving things in exchange for our money. From the provider's point of view, this bond also makes sense - he always gets paid when a service is consumed. So is there any catch? Yes, a big one!
When we see two actions closely linked, it doesn't mean that we should implement them that way. Technologically, payment and service usage are two separate operations that shouldn't combine because they would tie your hands together for several years. Still not following what's wrong here? We'll explain.
We often encounter the following implementation. You want to rent a bike, and part of the request processing to unlock the cycle is to check for a registered payment card in the user account. It is nothing else than another level of verification and authorization of the request to unlock the wheel. The API accepts the request, begins processing it, and then rejects it. API should have implemented authorization rules for the incoming request. These rules should apply to each request and decide if the user can unlock the bike or not.
If I don't have a registered credit card, the API will not accept my request anyway. This might bring some complexity to the implementation and testing, but it pays off. Why?
Making service consumption dependent on direct payment is a shortcut that does not work in the long term. On the other hand, building it as two separate domains can open your mobility service to new customers and new business models. How's that?
Imagine you run a successful bike-sharing service, and a big corporation would like to offer your service as a benefit to their employees. You will flag these users in your database and authorize them to use the service. Then you can happily charge the corporation in one hefty fat invoice.
Or imagine yourself as an operator of the bike-sharing service. One day, some big hegemons will enter your city with a massive customer base and technologically advanced solutions willing to integrate your service. If you use a user's credit card as an authorization measurement, you will face a lot of trouble and can't proceed. Users using accounts from big players have no desire to register in your app and give you a credit card number, and you're trapped.
But if you draw a thick red line between service consumption and payments, you can happily get integrated into more prominent platforms. Your bike-sharing service will serve as infrastructure and become a fundamental part of your town's whole mobility ecosystem. Hooray!
Reach out to get more information.
Jirka, co-founder