34 Let's Talk About the Progressively Evolved Architecture of Refactoring Excellence

34 Let’s Talk About the Progressively Evolved Architecture of Refactoring Excellence #

Every programmer has a dream of becoming an architect. But is the goal of becoming an architect “unattainable”? From my work experience, I have been responsible for the architecture of four hundred million-level products, such as Sogou Input Method and WeChat. Some may be curious about how the architecture design is done for these large-scale apps. Based on the reality of these apps that I have taken over, it can be seen that beneath the seemingly glamorous exterior lies a multitude of problems: haphazard log output, rampant singleton usage, chaotic lifecycle management, indiscriminate thread creation, and widespread thread safety issues.

Therefore, you can see that every large-scale application carries a heavy burden of technical debt from its history. One important task for an architect is to refactor the outdated architecture. In the upcoming “Architectural Evolution” module, we will learn together how to refactor and evolve architecture, helping us to repay these “historical debts” in a timely manner.

Although we talk about “architecture” every day, have you ever wondered what exactly architecture is?

What is Architecture #

Everyone has their own understanding of what architecture is. In my opinion, architecture refers to providing appropriate solutions to meet the needs of the business scenario, enabling the business to iterate quickly and achieve the goal of “improving quality and increasing efficiency”.

Let me give you an example to illustrate what architecture is and its role. In order to solve the requirement of UI rendering stuttering, we designed an architecture that involves asynchronous creation of views, asynchronous layout, and main thread rendering. However, architecture is just an abstract design, and for the specific implementation, we can call it a framework. A good framework can hide parts that we don’t need to concern ourselves with, improving our efficiency. For example, Facebook’s Litho and WeChat’s Vending solve the problem of UI thread stuttering in Android applications through framework constraints and asynchronous processing.

If monitoring is aimed at identifying problems with a focus on “prevention,” then good architecture can directly prevent problems from occurring. Therefore, the aim of architecture design is “treatment.” To help you better understand architecture, let’s start with the architecture design of Android.

1. Android Architecture

In the official documentation on “Platform Architecture” of Android, it is described as follows:

Android is a Linux-based, open-source software stack created for a wide array of devices and form factors.

Before delving into the Android architecture, let’s first consider the requirements of Android, that is, the demands from various parties.

  • Users. The ability to run various applications smoothly on low-memory devices, with long-lasting battery life.

  • Developers. Easy application development and the ability to generate revenue on the platform.

  • Hardware manufacturers. Both chip manufacturers and smartphone makers can adapt and upgrade their systems at a low cost.

When we recall the birth of Android, it gained support from hardware manufacturers, developers, and users in order to unite all possible forces. Therefore, when designing the architecture, these factors were taken into full consideration.

  • Java API layer. For a long time, Java has consistently held the top position as the most widely used programming language, with a large developer base. From that perspective, it was a wise decision for Android to choose Java as the interface language. Looking at it today, it was just a missed opportunity not to acquire Sun before Oracle, which has led to the current patent litigation quagmire. In summary, developers can use the various abilities of the system and hardware, and quickly build their own applications through the user-friendly interface layer using the Java language that they are already familiar with.

  • Hardware Abstraction Layer (HAL). Device manufacturers need to develop hardware drivers for the kernel. In order to reduce the development cost for device manufacturers, Android chose the mature and open source Linux kernel, and turned Android into a free and open source operating system, attracting more phone manufacturers to join. However, chip manufacturers and phone manufacturers still need to work together extensively to update to the latest system. After Android 8.0, Android introduced the HAL Hardware Abstraction Layer. It shields the specific implementation of the hardware, allowing phone manufacturers like Xiaomi to skip chip manufacturers and independently update the Android Framework.

  • Application Layer. When Android was designed, it considered various limitations of mobile devices. In order to provide a better experience on low-memory devices, a lot of work was done. For example, a register-based architecture was designed, the Dalvik virtual machine was created with smaller executable files, and the Low Memory Killer function was added to the kernel. In order to meet users’ basic needs, Android system initially included many basic applications. And by attracting more developers, it continues to meet users’ various needs and scenarios. Of course, Android also continues to optimize the performance of Framework and Runtime, such as the previously mentioned Project Butter and power optimization.

Architecture is designed to serve various scenarios, and Android’s architecture is designed to better meet the needs of hardware device manufacturers, developers, and users. I highly recommend you take a look at “About Android Design and Its Significance” and “Android Technical Architecture Evolution and Future” to gain a deeper understanding of Android system design and the technical support for system development.

2. How to choose architecture

For Android developers, many architectures and frameworks are already mature. Usually, we face the problem of how to choose the right framework for our own application. Looking back at what we have learned in this series, we have already made choices multiple times, such as which high-quality network library to use, OkHttp, Cronet, or Mars, and how to choose between JSON and Protocol Buffers for data serialization.

Whether it’s the network library, image library, UI framework, messaging framework, or storage framework, there are numerous solutions, both on GitHub and by Google. During the selection process, we primarily need to consider the following three factors:

  • Maturity of the framework. Has the framework been widely adopted, especially by applications with billions of users? Additionally, is the framework currently maintained and how is its performance?

  • Maturity of the tool chain. Are the supporting tools mature and complete? For example, as a new technology, does Flutter have a complete tool chain support for development, compilation, testing, and deployment?

  • Learning curve and completeness of documentation. Considering the current state of the team, we need to evaluate whether the learning curve of a framework is acceptable, whether the learning path is smooth, and whether there is sufficient documentation and community support.

When it comes to architecture selection, Conway’s Law is an important guideline. I recommend reading the article “Understanding the Pain of R&D from Conway’s Law and Technical Debt” to understand how our organizational structure, code architecture, and processes should be matched to the scale of our team. How should we interpret this statement? It means that architectural design or selection should not aim too high. We should only provide as much support as our team’s scale requires. Be cautious of doing long-term things in the short term or doing short-term things in the long term.

WeChat began modularization in 2013, while at the same time, Taobao underwent componentization. Why was there such a difference? At that time, WeChat had only one team developing the Android side, with fewer than 30 people. To isolate the code, WeChat moved basic components to a separate repository handled by dedicated personnel. For business purposes, they still kept the same repository, but split it into different business modules. Interested students can refer to the article “WeChat Android Modular Architecture Refactoring Practice”.

On the other hand, for Taobao, there were hundreds of people simultaneously developing on the same application, and these people belonged to different teams located throughout the country. Therefore, whether it was based on code protection or development efficiency, all business modules should be isolated, meaning that each business module should be in a separate repository.

What is architectural evolution #

“There are no insurmountable obstacles, only endless obstacles.” In the process of business development, new problems always arise, and some old problems may no longer exist at some point in development. For example, in order to be compatible with Android 4.X, we did a lot of compatibility design in architecture back then, but when we no longer need to be compatible with 4.X devices, we can timely abandon these burdens.

1. Why do architectural evolution

Architecture is meant to serve the needs of business scenarios, so it needs to adjust according to the changes in business. In other words, architecture needs to evolve with the development of the business.

“If you have an illness in your body, it will become deep if left untreated.” WeChat undergoes a major restructuring every year because we insist that code architecture will eventually deteriorate and need to be rebuilt rather than constantly patched. Architectural evolution can bring the following changes to a team:

  • Break dissatisfaction. We need to break conservative practices and proactively face shortcomings. The team needs to start refactoring regularly and release everyone’s dissatisfaction with the code. Transform the decay of the architecture (reduced efficiency, increased complaints) into motivation for architectural optimization.

  • Rebuild trust. Promote module refactoring periodically. Solving some problems often motivates more people to try.

  • Team development. Refactoring is also an opportunity for team progress, allowing more members to master architectural skills, cultivate a sense of architecture for everyone, and achieve “everyone is an architect”.

However, we need to have the ability to discern in the process of architectural evolution, which is often referred to as “technical vision”. This includes the choice and comparison of various technology stacks and architectural design considerations. It requires a reasonable judgment based on the business and the current situation of the team. It’s important to know clearly what actions will bring the greatest benefits.

The negative example here may be that after painstakingly creating a set of wheels, it turns out that others have already done it and even better. The reason for this problem lies in your technical vision. In the “High-Quality Development” and “Efficient Development” modules, I have repeatedly shared with you the latest practices of domestic and foreign giants, hoping to enhance our technical vision. Especially in the “Efficient Development” module, some students may think that these topics are too broad and not directly related to themselves. In fact, every step of the application development process is related to you and me, and it involves a lot of content. Each part can be an independent column. As an “Android Development Master Course”, I want to present you with a complete architectural design from a top-level perspective, rather than analyzing specific optimization details. All of this is to help you view problems from a higher perspective and comprehensively improve your technical vision.

Developing technical vision may not have many shortcuts, and it requires long-term practice and repeated trials and setbacks to grow from a “giant baby” to a “master”.

In the “Architectural Evolution” module, to further help us improve our technical vision and architectural skills, I have prepared the following content:

  • GOT Hook, PLT Hook, Inline Hook. I will compare the principles and differences of these three Native Hook frameworks and tell you how to choose. And I also have some experiences in Native development.

  • With all the buzz about front-end development, how to evolve and choose, how to choose the right cross-platform and dynamic solution for our application.

  • With technology constantly advancing, how should we consider whether to keep up with new technologies? Can Flutter really dominate the world?

  • In addition to application development, we have invited three experts to introduce their experiences in mobile gaming, audiovisual, and AI development. What are the architectures in these areas, and how can we learn and transform in these fields.

2. How to do architectural evolution

Architectural evolution is necessary, but we need to fully realize the difficulties, and actually doing it is much harder than we think, especially with various historical baggage issues. The evolution of architecture is usually accomplished through refactoring. If we are determined to refactor, I have two suggestions for you:

  • Progressive and tailored to the team’s current situation. It is difficult to find a solution that excels in performance, cost, and time. We need to balance the relationship between these three factors. If we have enough time, we can strive towards better performance goals. But if time is limited, we can refactor in stages.

  • Measurable with results at each stage. Architecture evolution should not focus on simply making big moves. It is better to implement it in stages, with measurable results at each stage. This allows team members to quickly experience the benefits of optimization and encourages more people to participate in the refactoring process.

In the article “Android Technical Architecture Evolution and the Future,” the release timeline of Android versions is reviewed. Android releases a new version every year, each with various levels of refactoring. The purpose of refactoring remains to better meet the needs of users, developers, and hardware vendors. For example, to improve the battery life of smartphones, let’s review the evolution of power optimization in Android.

To make applications run faster, Android Runtime is also optimized in every version. The following is the evolution of Android Runtime in each version.

The differences in the operation mechanism of the virtual machine and its evolution in various versions are often asked about in interviews by many companies. Here are some good resources comparing the evolution of virtual machine architectures, which I would like to share with you.

Android 8.0’s Treble plan introduced the HAL (Hardware Abstraction Layer) to solve the problem of difficulty in hardware vendor upgrades. However, even if vendors upgrade to the latest system, they cannot directly deliver it to users. There is still the issue of application compatibility. Why did Android P strongly introduce restrictions on the Hidden API? The initial consideration was not about security but to reduce the compatibility adaptation time for each Android version upgrade and accelerate the release pace of Android versions.

The design of Hidden API also takes into account the considerations of architectural evolution. Android does not want to encounter the burden of external application compatibility and adaptation whenever a private method in the Framework is modified.

This is true for both the Android system and the architectural evolution of applications. Due to various performance issues caused by componentization, Alipay and Taobao have also adapted to these changes in architecture. In terms of engineering structure, they still maintain code isolation for components in the repository. However, in the final product, componentization has returned to modularity, and non-core businesses will gradually migrate to H5 or mini-programs.

Whether it’s WeChat, Alipay, or Taobao, everyone wants to become a super app and strive to become a micro-operating system that meets as many user demands as possible. The architecture of applications also needs to adapt to the transformation of business forms. The article “Agile Development and Dynamic Updates in the Alipay App” describes the transformation of Alipay’s development approach driven by architectural upgrades in recent years. I recommend you read it carefully.

Summary #

From the initial exposure to architectural design to mastering the essence of architecture, it can be said that there are no shortcuts. The growth of architectural design capabilities is built upon encountering pitfalls and carrying out refactoring time and time again. However, becoming an architect is not an “unattainable” goal; we can exercise ourselves repeatedly in our daily work.

Architectural design does not necessarily mean the design of an entire application or system; it can also refer to the design of a module or a requirement. When taking on a requirement, we can set higher requirements for ourselves and consider the problem more meticulously. For example, how to minimize the impact on existing code, how to implement functionality quickly and clearly, how to better encapsulate components and controls during the development process, how to optimize performance, and whether there are any new technologies that can assist in developing this requirement.

Homework #

A technical person should have a representative work in their life, giving their technical career an account. In your work, have you ever had a satisfying architectural design (for an application, a module, or a framework)? What are your thoughts on architectural evolution and what problems have you encountered? Please leave a comment to share with me and other classmates.

Feel free to click “Please Read to Friends” to share today’s content with your friends and invite them to study together. Finally, don’t forget to submit today’s homework in the comments section. I have also prepared a generous “Study Boost Package” for students who complete the homework seriously, and look forward to discussing progress with you.