Professional Documents
Culture Documents
cs446-d6 9 Digital Business Cards
cs446-d6 9 Digital Business Cards
Architecture
Our system is designed to meet all the functional requirements specified in the project proposal,
including the creation, customization, and sharing of digital business cards, along with advanced
management and networking features. Through the use of modern templates, users can easily create and
customize their business cards to reflect their professional identity. The system supports a wide range of
information fields such as name, company, contact information, and links to professional profiles,
ensuring that users can convey a comprehensive digital representation of their professional selves.
The sharing of business cards is facilitated through three innovative methods: QR Codes,
Bluetooth, and link sharing. This versatility allows users to exchange their digital cards in various
scenarios, from face-to-face meetings to virtual networking events, enhancing the applicability of the app
in today's digital-first professional environment. Moreover, our application allows users to manage their
cards effectively, with features to save, delete, duplicate, and tag cards for different contexts and usage
scenarios. This level of control and flexibility ensures that our system meets the diverse needs of our user
base.
Our application is also optimized for high performance, with specific attention given to the
responsiveness of the user interface and the efficiency of data operations. We can measure performance in
terms of load times for opening the app, creating and customizing business cards, and the speed of sharing
and receiving cards. Our benchmarks enable us to aim for load times to not exceed 2 seconds for any
functionality within the app on standard mobile hardware, ensuring a smooth and efficient user
experience.
Scalability is a core aspect of our system's architecture, particularly in handling a growing
number of users and an increasing volume of data. Our use of Firebase's Firestore and Storage services
allows our application to scale seamlessly with demand. We measure scalability in terms of our system's
ability to maintain performance levels under varying loads, intending to support up to 100,000 concurrent
users without degradation in response times or functionality based on Firebase availability.
Reliability is ensured through comprehensive error handling and robust data management
practices. Our system aims for as close to a 99% uptime as possible, with real-time data backup and
recovery mechanisms to prevent loss of user data leveraging Firebase. We employ testing through builds
and continuous integration practices to identify and resolve potential issues proactively, ensuring our
application remains reliable and functional at all times.
User experience is a critical non-functional requirement, with the system designed for
intuitiveness, ease of use, and accessibility. We utilize user feedback and usability testing to continuously
refine the UI/UX, ensuring that users of all technical skill levels can navigate and utilize the app
effectively. Satisfaction metrics and user engagement rates are closely monitored to gauge the success of
our user experience efforts.
In conclusion, our digital business card application is engineered to meet the specified functional
and non-functional requirements through a combination of strategic architecture choices, cutting-edge
technologies, and a user-centered design philosophy. By adhering to these principles, we ensure that our
app not only fulfills its intended purpose but also provides a reliable, efficient, and enjoyable experience
for all users.
Client-Server Architecture
We used a client-server architecture style to encapsulate the functionality of events. We have a
server to allow users to host and join our events, and request user cards to download. To store and manage
the data we use Firebase’s Firestore and Storage where CRUD operations update collections in the
NoSQL Firestore while image uploads and downloads interact with the Firebase Storage. From the
client’s perspective, we use HTTP requests to perform various tasks such as creating/editing/joining
events, adding user cards to events, leaving/deleting events, checking if events exist, requesting all cards
within an event, adding a card to a user (based on a userID provided by the server), and
uploading/downloading the card images. The client-side API functionality is implemented within
ApiFunctions.kt and called upon within the MainActivity.kt, EventMenuScreen.kt, EventCard.kt,
ShareDialog.kt, and ReceiveDialog.kt files for the views and event card/dialog components, and within
the event view model EventViewModel.kt. In views, we allow creating/editing/joining events using the
Add Event Floating Action Button (FAB), an event card’s edit button, and the join dialog. The card and
image upload/download occur in the share dialog, and receive dialog/card download button respectively.
In the event menu screen, we retrieve all cards within an event to display for the user.
Queries are processed via two methods. The route itself considers path parameters to reference
what resource to perform CRUD operations on. For example, the GET route “/user/{user}/card/{card}” is
implemented in handlers/card.go, inside the Card handler retrieves a card with ID “{card}” from the
user with ID “{user}”. Also, for sending data and returning typed object values the objects are passed as
JSON and are marshalled into the appropriate types on the backend via Go’s JSON library. All the router
setup, loading of secrets, and initialization of Firebase clients are done in main.go. The associated types
for business cards and events are defined in models/card.go and models/event.go respectively. The
handlers managing users, user cards, and events are found in handlers/user.go. handlers/card.go, and
backend/handlers/event.go respectively. Finally, any middleware used is found in the
backend/middlewares directory.
Our deployment diagram shows this architecture clearly, with our server handling all operations
regarding our Firestore database, and the deployment on fly. Our application directly interfaces with this
server through our API and can pull required data (BusinessCards, users, etc) through HTTP requests.
Component Diagram
Deployment Diagram
Design
Designing a system in a way that is both comprehensive and easy to understand requires careful
consideration of architecture, class structure, and external interfaces. Our system has 3 main components:
User Interface (UI), Business Logic and Data Management. UI interacts with Business Logic, which in
turn interacts with Data Management to fetch/store data. Each of our components is designed to be
modular and independent, allowing for easy integration and testing. Here is a basic summary of our
design, along with its rationale (the details can be found in the class diagram).
Observer Pattern. Android provides StateFlow, LiveData, and MutableState which are observables (their
name for subjects), and are used everywhere we need to store a state that can emit updates to UI elements,
other components, etc. This was heavily used for any view or viewmodel such as AppViewModel.kt or
BusinessCardModel.kt, as our MVVM structure made Androids subjects and the observable the go-to
solution to updating views and viewmodels with data changes.
Delegate Pattern. To decouple the sending of data over Bluetooth with the actual operations performed
on that data, BluetoothRepository.kt uses a delegate to handle the process of executing model changes
after a card is received. This was also intended for Nearby Share, as it allowed any transfer procedure or
protocol to work with the rest of the codebase.
Repository Pattern. Bluetooth needs a repository due it being a very limited system resource.
Consequently, a single repository is responsible for Bluetooth resource management in
BluetoothRepository.kt and its related services BluetoothShareService.kt and
BluetoothReceiveService.kt is used.
Coupling:
Our application is designed to work in components sharing data through observers. delegates, or classes.
For example, the Sharing functionality is split into 6 distinctive fragments that are not coupled to each
other:
Uploading - Packing - Sending - Receiving - Unpacking - Saving- Actioning
While Bluetooth and QR Codes handle all these steps internally, they are strictly defined such that you
can extract or delegate them to separate classes or instances. In this way, our app is designed to be
infinitely alterable, since we developed many of the components under the assumption they would be
replaced, superseded, or scrapped during the design, prototyping, or testing process.
An example of a potential change that we could add and would be supported by our current
architectural style would be enhanced security throughout our sharing processes. A specific example
would be introducing end-to-end encryption for the data we’re sharing, and the business card information
to prevent any middleman attacks that may come up. Since our MVVM design allows each component to
be isolated, and our Bluetooth segment is entirely decoupled from the rest of the system, introducing
encryption algorithms at the receiving end and the sending portion would be non-disruptive to the rest of
our viewmodels. Uploading, sending, saving, or receiving patterns wouldn’t be impacted, as our
viewmodels operate independently of our sharing systems.
Furthermore, our use of observers for component communication allows the introduction of this
new feature without hiccups. If encryption would require additional data verification steps, they can be
integrated as new components or extensions of existing systems with little impact on our overall system
architecture.
Class Diagram