Research & Development projects
Is the Android app architecture necessary? At the outset, the answer to the question posed in the title is a resounding “yes.” Even if the architecture is not intentionally planned, it still exists within the application. The challenge lies in its lack of careful consideration, often resulting in negative consequences, such as excessive focus on bug resolution. In essence, poor architecture can become a maintenance nightmare for the application.
Identifying signs of poor architecture is crucial. When developers complain about the difficulty of adding or changing code, it’s often a symptom. This happens because developers add code according to their knowledge and skills without aligning with an established architecture. The lack of a defined architecture leads to disjointed coding practices.
Comparing this situation to building construction, it’s akin to builders using different materials for each room. One uses bricks, another metal, and yet another wood. The problem arises when attempting to integrate these disparate elements. Without a decision on the core architecture of the application and the materials to be used, integration becomes chaotic, resulting in potential breakdowns.
Building on a flawed architecture makes introducing errors into the code easy. This situation occurs when a programmer is unaware or unsuspecting, inadvertently impacting other functionalities within the application.
The effects of building, according to a so-called spaghetti architecture, often manifest as resolving one issue in one place only to encounter new errors in another functionality. The lack of cohesion leads to an ongoing cycle of problem-solving.
Frequently, high crash rates stem from components being initialized in a random order, making it unpredictable. Inadequate architectures often witness the use of mutable objects for ease, resulting in losing control over the application’s state.
Updating or changing a library becomes a significant challenge, often necessitating a complete rewrite of a large part of the application and readdressing the same issues. In well-constructed architectures, functionalities from a library are often isolated through an additional layer, defining expectations from that functionality.
For example, let’s consider the “Analytics” functionality. You want to send information about what users are doing in the application. Initially, clients use Firebase for this purpose, but if it proves insufficient later, they may want to use another tool. In this case, when you don’t have an additional layer through which all events pass, switching tools requires making changes in almost every application screen.
Deciding whether it will be an MVP, MVVM, or perhaps MVC is not enough to build a good architecture. It’s about the team’s approach to developing the application. There are several ways to approach this.
In this approach, a team leader is appointed, and this person makes decisions about the most critical aspects of the application. This individual needs to be highly communicative and open to discussions within the team about various aspects of the application. Potential problems should not be trivialized.
Another possibility is for the team to create a good architecture without appointing a team leader. This requires code reviews and ample space for team discussions about the application’s current state and development direction. If the application deadline is tight, and there is pressure to deliver components quickly, architecture may not be considered a priority. In this case, even in an experienced team, there is a risk that the application’s architecture will be rather weak.
Below, I’ll provide some guidelines that can help build good architecture, but providing flexibility is crucial. Every application is different, with slightly different tasks to perform. Therefore, the architecture must be adapted to the application rather than trying to adapt the application to a preconceived architecture described in some articles.
One application may have a database, while another may not. The same goes for connecting to APIs or interfacing with external devices. Sometimes, there’s an application without a user interface but with sophisticated components. Some applications can be termed wholesale (white label). Each type of application may require a different architectural approach, and it’s important not to apply a one-size-fits-all solution.
Several tools facilitate application architecture design. In the context of Android, the MVVM (Model-View-ViewModel) pattern is well-supported and considered the best choice currently.
MVVM serves as a starting point, but selecting tools for dependency injection is crucial. I recommend using Dagger Hilt or Koin, both tools are effective, with the preference leaning towards Dagger Hilt for its error verification during compilation.
Defining the relationship between ViewModel and the rest of the application is pivotal. Advocating for the use of patterns such as use case and repository, the choice between them may depend on the specific application or team agreements.
The arrangement of the project structure plays a vital role. Creating a “domain” module containing interfaces and data models used throughout the application is favored. Individual features are built in separate modules with implementations of interfaces. Kotlin-DSL proves invaluable in building and maintaining multi-module applications.
Implementing practical tips related to Android app architecture, tool selection, and project structure significantly benefits software development projects. A well-designed architecture simplifies code changes, accelerates bug fixes, and prevents recurring issues. It facilitates the integration of new team members, expediting project development.
Investing in a robust architecture is worthwhile. A well-thought-out structure allows developers to focus on adding new features and improving existing ones without fear of damaging functioning solutions. Ultimately, good architecture contributes to efficiency, scalability, and the long-term success of a project.