Table of contents
- First lets talk about the differences compared to app development
- Now, let’s learn the art 😁
- Think API First (Most Important)
- Simplify Initialisation and integration
- Think of the Host clients and be a Good Guest
- Try to Avoid Third-Party Libraries Within the SDK
- Testing, Testing, and More testing
- Documentation & Sample Application
- Read Internals of High-Quality Frameworks and Libraries
"In the dynamic world of mobile technology, while a successful app can reach millions, an ingeniously engineered SDK is a quiet yet powerful force with the potential to touch and transform the digital experiences of billions, standing as the unsung hero behind the curtain."
In the evolving landscape of mobile engineering, the development of mobile and platform SDKs is a critical yet often underrepresented field. I have been developing mobile and platform SDKs for quite some time now and have noticed a significant lack of resources focusing on this particular aspect of mobile engineering. This article is an endeavour to consolidate my learnings to help the community write better SDKs. It is designed to be platform-agnostic, offering insights that can be applied universally across all mobile platforms.
First lets talk about the differences compared to app development
The major differences between app development and sdk development are:
Target Audience:
App Development: While creating apps we are targeting customers, typically a non-technical user base. They are not much concerned about the internal workings as long as the app solves their problems.
SDK Development: Here, our target audience consists of other developers, most of whom are interested in the internal workings. We need to solve for their pain points and help them achieve what their customer or product wants.
Design and Usability:
App Development: When creating apps, our first focus is usually on core functionality and customer experience.
SDK Development: In SDK development, our focus should be on solid API design, ease of integration, scalability, testing and developer experience.
There are many more nuances between the two, but I am not going into those nitty-gritty details to keep the article focused at the topic at hand.
Now, let’s learn the art 😁
Think API First (Most Important)
After the developer opts for our SDK as the appropriate solution, the exposed APIs serve as their initial point of interaction. Consider the best frameworks and SDKs you have encountered in your journey. They typically offer intutive and easy to understand APIs don’t they? When updates are required, often all you do is change their version number, and everything works seamlessly. You rarely need to delve into the internals to resolve your issues. That’s our aim. It’s crucial to meticulously plan API design before release. Any changes in exposed APIs can become significant pain points for users. The larger the user base, the more pronounced the impact, affecting their delivery cycles and end customers. So, when designing APIs always keep these major points in mind and try to adhere to them:
⭐️ Collaborative Design: Work closely with stakeholders in designing APIs. Getting the APIs right is vital for a long-lasting, stable SDK.
⭐️ Compatibility: Ensure that your APIs are backward and forward compatible, allowing for future enhancements without breaking existing implementations. Any change in a version upgrade can potentially break the client if it’s not backward compatible. A well-designed API eases integration and adaptability across different applications.
⭐️ Robust Integration Testing: Keep your API integration tests current and robust. These tests are your first line of defence for quickly identifying breaks.
⭐️ Information Exposure: Expose only the necessary information. Remember, the client doesn’t need to know the SDK’s internals. They require only the minimal information necessary to address their use cases.
So, how to design awesome API’s you ask, well it would require a separate article in itself 😅
Simplify Initialisation and integration
This aspect varies significantly across SDKs, largely depending on the use case. Generally, taking a configuration object as input during initialization works well. However, if your SDK requires many parameters, you might need to create or provide a JSON file. A familiar example for mobile developers is the firebase.json required by the Firebase SDK - a file many of us encounter frequently😃. When it comes to simplifying initialisation and integration, these are the key points that stand out:
⭐️ Minimal Configuration: Aim to require only the minimum number of parameters or objects necessary for your SDK. Ideally, you should take elements that allow you to construct the necessary objects internally. This approach prevents users from being overwhelmed with creating these objects themselves.
⭐️ Keep it Modular: Enable developers to integrate their components into your SDK. It’s crucial to determine which components should be configurable and which should not. Configurable elements need to adhere closely to the Open-Closed principle, ensuring extendability without modifying the existing code.
Think of the Host clients and be a Good Guest
Your SDK should ideally be usable by clients worldwide, so it’s important to keep your API levels to the minimum required and aim for high scalability and reusability. Consider the world’s best libraries: most apps can use and extend them for their use cases. These libraries are reliable and resilient, functioning effectively across various clients and scenarios. This is what we should aim for. Here are some crucial points to keep in mind to be a considerate guest in your client’s app:
⭐️Transparency with Clients: Clients should be well-informed about what the SDK is doing. For instance, if the SDK logs activities, clients should be aware of this and have the option to disable it. Important details that directly impact the client should be clearly communicated, so that the clients can make informed decisions.
⭐️ Architecture for Scalability: The SDK should be designed to handle a wide range of applications and usage intensities. This might involve using design patterns that support scalability, like modular architecture, to ensure that different components within the SDK can scale independently.
⭐️ Minimising App Size Impact: Ensure that your SDK minimally impacts the client’s app size. Any additional overhead resulting from SDK usage should be clearly stated in the documentation upfront.
⭐️ Performance Optimisation: Optimise your SDK for performance at the code level. This includes efficient memory management, CPU usage, and minimising battery consumption. Any unoptimised code here is an additional overhead for the client which they can’t modify or improve.
⭐️ Security and Privacy: Implement robust security and privacy measures that can handle diverse use cases and users without compromising data integrity. This includes secure data storage, transmission, authentication, and authorization practices.
Try to Avoid Third-Party Libraries Within the SDK
Consider this: for the client, our SDK is already third-party code. Introducing additional third-party code within our SDK adds complexity and could lead to regressions or conflicts, especially if the client is also using that same library. This doesn’t mean you should always create custom solutions from scratch—there’s no need to reinvent the wheel. For instance, using a well-tested and well-known library that works effectively is fine, but it should be tailored specifically to the needs of the SDK. It should not be directly exposed to the client, as this could lead to an abstraction hell. Essentially, the SDK should remain focused on addressing the core problem statement.
Testing, Testing, and More testing
I cannot emphasize this enough: thorough testing of the SDK is imperative. Even a minor bug in the SDK can cascade into all host apps utilizing it. Put yourself in the developers’ shoes, imagine debugging an issue in your app, only to find that the root cause is a bug in an SDK, one that you didn’t write and cannot modify because it’s part of the read-only build files. Frustrating, right? Now consider the impact on the end users, the customers. A single SDK bug could potentially affect billions of users. In my view, the ideal approach is test-driven development:
⭐️ Problem Statement and Documentation: Understand the problem statement and document your High Level Design and Low Level Design, and have it validated by your team and stakeholders.
⭐️ Comprehensive Testing Plan: Prepare a detailed unit and integration test plan covering both exposed and internal APIs. Write tests to address these aspects thoroughly.
⭐️ Development with Testing in Mind: Begin your development with the aforementioned points in mind. Your code should be crafted to pass these tests successfully.
⭐️ Bonus Tip: Consider consulting ChatGPT or an AI assistant for your test plan. They can often provide unique perspectives on potential edge cases.
Your approach may vary, but the importance of rigorous testing in SDK development cannot be overstated.
Documentation & Sample Application
Ensuring a high standard of documentation accessible to users is crucial. Ideally, the entire SDK, encompassing both internal and exposed APIs, should be thoroughly documented. However, at a minimum, it’s imperative to document the public APIs to a high quality standard. Reflect on the documentation of well-established frameworks and SDKs, that’s the level of quality we’re aiming for. Additionally, where feasible, make your design documents public and consider open-sourcing your code. The long-term benefits of this are significant, as it allows users to identify optimizations or bugs and directly submit change requests. I recognize that open-sourcing the entire codebase may not always be feasible. In such cases, setting up a robust forum where users can offer feedback and report issues is a viable alternative. It’s also important to provide comprehensive sample applications that demonstrate the full capabilities of the SDK. Keep in mind that these samples are public and represent the SDK’s brand value, therefore, their quality should be at par with the SDK’s overall quality.
Read Internals of High-Quality Frameworks and Libraries
There’s a famous quote that says, “We become what we consume.” It’s beneficial to develop a habit of delving into the internals of high-quality open-source libraries. Observe the practices they follow and understand the methodologies that contribute to their excellence. Then, try to incorporate relevant practices into your own work. The learning derived from this process is immense and can significantly contribute to our growth as developers.
There is much more to this art of designing the SDKs, I believe the above pointers cover a good gist and provide a good starting point. I will keep updating the article if I learn anything new regarding these.
You can further explore these resources:
https://www.instabug.com/blog/sdk-development-interviews
https://foresightmobile.com/blog/mobile-sdk-best-practices-for-developers
I would love ❤️ to hear your feedback. Please comment your opinions or suggestions also do let me know about your experiences with SDK development and which parts interested you the most 😃. Oops, Found a mistake in the above 🥹 do let me know, I will correct it at once and will mention you in credits at the top. Thanks again
You can find me at:
LinkedIn: https://www.linkedin.com/in/sankalpchauhan-me/
Twitter: https://twitter.com/iSankalpChauhan
Website: sankalpchauhan.me
Email: sankalp@sankalpchauhan.me