Tutorial and Example for Advanced Programming 2024 - Faculty of Computer Science, Universitas Indonesia
In this repository, we have provided you a REST (REpresentational State Transfer) API project using Rocket web framework.
This project consists of four modules:
controller
: this module contains handler functions used to receive request and send responses. In Model-View-Controller (MVC) pattern, this is the Controller part.model
: this module contains structs that serve as data containers. In MVC pattern, this is the Model part.service
: this module contains structs with business logic methods. In MVC pattern, this is also the Model part.repository
: this module contains structs that serve as databases and methods to access the databases. You can use methods of the struct to get list of objects, or operating an object (create, read, update, delete).
This repository provides a basic functionality that makes BambangShop work: ability to create, read, and delete Product
s.
This repository already contains a functioning Product
model, repository, service, and controllers that you can try right away.
As this is an Observer Design Pattern tutorial repository, you need to implement another feature: Notification
.
This feature will notify creation, promotion, and deletion of a product, to external subscribers that are interested of a certain product type.
The subscribers are another Rocket instances, so the notification will be sent using HTTP POST request to each subscriber's receive notification
address.
You can download the Postman Collection JSON here: https://ristek.link/AdvProgWeek7Postman
After you download the Postman Collection, you can try the endpoints inside "BambangShop Publisher" folder.
This Postman collection also contains endpoints that you need to implement later on (the Notification
feature).
Postman is an installable client that you can use to test web endpoints using HTTP request. You can also make automated functional testing scripts for REST API projects using this client. You can install Postman via this website: https://www.postman.com/downloads/
- Set up environment variables first by creating
.env
file. Here is the example of.env
file:Here are the details of each environment variable:APP_INSTANCE_ROOT_URL="http://localhost:8000"
variable type description APP_INSTANCE_ROOT_URL string URL address where this publisher instance can be accessed. - Use
cargo run
to run this app. (You might want to usecargo check
if you only need to verify your work without running the app.)
- Clone https://gitlab.com/ichlaffterlalu/bambangshop to a new repository.
- STAGE 1: Implement models and repositories
- Commit:
Create Subscriber model struct.
- Commit:
Create Notification model struct.
- Commit:
Create Subscriber database and Subscriber repository struct skeleton.
- Commit:
Implement add function in Subscriber repository.
- Commit:
Implement list_all function in Subscriber repository.
- Commit:
Implement delete function in Subscriber repository.
- Write answers of your learning module's "Reflection Publisher-1" questions in this README.
- Commit:
- STAGE 2: Implement services and controllers
- Commit:
Create Notification service struct skeleton.
- Commit:
Implement subscribe function in Notification service.
- Commit:
Implement subscribe function in Notification controller.
- Commit:
Implement unsubscribe function in Notification service.
- Commit:
Implement unsubscribe function in Notification controller.
- Write answers of your learning module's "Reflection Publisher-2" questions in this README.
- Commit:
- STAGE 3: Implement notification mechanism
- Commit:
Implement update method in Subscriber model to send notification HTTP requests.
- Commit:
Implement notify function in Notification service to notify each Subscriber.
- Commit:
Implement publish function in Program service and Program controller.
- Commit:
Edit Product service methods to call notify after create/delete.
- Write answers of your learning module's "Reflection Publisher-3" questions in this README.
- Commit:
This is the place for you to write reflections:
In the Observer pattern diagram explained by the Head First Design Pattern book, Subscriber is defined as an interface. Explain based on your understanding of Observer design patterns, do we still need an interface (or trait in Rust) in this BambangShop case, or a single Model struct is enough?
- Menurut saya, untuk kasus BambangShop, sebuah struktur Model
Subscriber
sudah cukup untuk pattern Observer karena dalam kasus ini, BambangShop hanya memiliki suatu modelProduct
yang memiliki atribut tipe yang akan di subscribe olehSubscriber
. Namun, jika BambangShop nantinya akan menambahkan model lain yang juga bisa di subscribe olehSubscriber
, akan lebih baik apabila terdapat sebuah interface atau trait untukSubscriber
.
id in Product and url in Subscriber is intended to be unique. Explain based on your understanding, is using Vec (list) sufficient or using DashMap (map/dictionary) like we currently use is necessary for this case?
- Dalam kasus ini, penggunaan
DashMap
tetap diperlukan meskipunid
dalamProduct
danurl
dalamSubscriber
unik. Hal ini dikarenakan kita ingin menyimpanSubscriber
berdasarkanproduct_type
dari suatuProduct
. Jika digunakanVec
, maka kita harus memetakan juga index dariVec
keproduct_type
, sehingga pada akhirnya akan menambah struktur data yang diperlukan juga. Dalam penyimpananurl
, akan lebih mudah dengan menggunakanDashMap
juga karena akan mempermudah penghapusanSubscriber
. Jikaurl
disimpan dalamVec
, maka ketika adaSubscriber
yang ingin berhenti subscribe terhadap sebuahproduct_type
, kita harus melakukan linear search untuk mencari objekSubscriber
yang relevan baru bisa menghapusnya dariVec
. Dengan menggunakanDashMap
, hal ini diharapkan dapat dilakukan dalam waktu konstan dibanding linear.
When programming using Rust, we are enforced by rigorous compiler constraints to make a thread-safe program. In the case of the List of Subscribers (SUBSCRIBERS) static variable, we used the DashMap external library for thread safe HashMap. Explain based on your understanding of design patterns, do we still need DashMap or we can implement Singleton pattern instead?
- Menurut saya, kita bisa-bisa saja mengimplementasikan pattern Singleton, namun tenaga yang harus dikeluarkan untuk mengimplementasikannya jugalah besar karena Rust memiliki banyak restriksi terkait static variable dan mutability. Sehingga, dalam kasus ini dimana kita hanya ingin menyimpan
Subscriber
berdasarkanproduct_type
yang di subscribe, menurut saya tenaga yang harus dikeluarkan terlalu besar dibanding apa yang ingin dicapai, sehingga akan lebih mudah menggunakan DashMap untuk mencapai apa yang kita inginkan.
In the Model-View Controller (MVC) compound pattern, there is no “Service” and “Repository”. Model in MVC covers both data storage and business logic. Explain based on your understanding of design principles, why we need to separate “Service” and “Repository” from a Model?
- Kita harus memisahkan
Service
danRepository
dariModel
agar setiap komponen dalam kode kita memenuhi prinsip Single Responsibility. Dengan memisahkanService
danRepository
dariModel
, kita memisahkan pula tanggung jawabModel
yang awalnya bertanggung jawab menghandle penyimpanan data, business logic, dan representasi data, menjadi hanya representasi data. Tanggung jawab penyimpanan data diberikan kepadaRepository
dan tanggung jawab business logic diberikan kepadaService
.
What happens if we only use the Model? Explain your imagination on how the interactions between each model (Product, Subscriber, Notification) affect the code complexity for each model?
- Ketika kita hanya menggunakan
Model
, kode di setiapModel
akan menjadi lebih kompleks karena banyak tanggung jawab lain yang harus di handle selain tanggung jawab representasi data. SebuahSubscriber
saja sudah berinteraksi banyak denganNotification
, seperti bisasubscribe
,unsubsribe
, diberikan notifikasi ketika ada perubahan padaproduct_type
yang di subscribe, dan bisa saja masih banyak lagi. Jika semua kode ini digabungkan ke dalam satuModel
, tentu akan susah untuk menentukan sebenarnya apa yang dilakukanModel
tersebut.
Have you explored more about Postman? Tell us how this tool helps you to test your current work. You might want to also list which features in Postman you are interested in or feel like it is helpful to help your Group Project or any of your future software engineering projects.
- Saya belum terlalu mengeksplor banyak mengenai
Postman
, namun dari apa yang sudah saya ketahui, alat tersebut cukup membantu dalam melakukan testing terhadap API yang saya buat. HTTP Request yang bisa dilakukan juga tidak sebatasGET
danPOST
sehingga saya bisa dengan mudah mengetes apakah endpoint tertentu benar hanya dapat menerima suatu tipe HTTP Request atau tidak. Terdapat juga fitur menambahkanHeaders
danAuthorization
yang menurut saya akan dapat digunakan dalam Tugas Kelompok saya atau projek lainnya yang menggunakan custom headers dan authorization. Secara keseluruhan menurut saya aplikasiPostman
sangatlah membantu melakukan API testing, dibanding harus membuat script sendiri atau mengetes langsung dengan browser.
Observer Pattern has two variations: Push model (publisher pushes data to subscribers) and Pull model (subscribers pull data from publisher). In this tutorial case, which variation of Observer Pattern that we use?
- Pada tutorial ini kita menggunakan model
Push
karena setiap kali ada perubahan padaProduct
(publisher),Subscriber
akan diberikan notifikasi melaluiNotification
. Ini bisa dilihat padasrc/service/product.rs
dimana ketika ada produk baru yang di buat, di hapus, atau di publish,NotificationService
akan digunakan untuk menotifikasiSubscriber
terkait.
What are the advantages and disadvantages of using the other variation of Observer Pattern for this tutorial case? (example: if you answer Q1 with Push, then imagine if we used Pull)
- Keuntungan jika kita menggunakan model
Pull
pada kasus tutorial ini adalah kita tidak harus mengirimkan notifikasi kepada setiapSubscriber
tiap kali ada perubahan padaProduct
, melainkanSubscriber
bebas untuk kapan saja meminta perubahan kepadaProduct
terkait. Ini tentu membuat server dimana web app kita dijalankan tidak memakan banyak resource setiap kali ada perubahan padaProduct
karena harus membuat thread-thread baru untuk mengirimkan notifikasi kepadaSubscriber
. Di lain sisi, kekurangan modelPull
pada kasus tutorial ini adalahSubscriber
harus secara aktif meminta data kepadaProduct
jika mereka ingin selalu mendapatkan perubahan terbaru yang ada padaProduct
terkait.Subscriber
tidak dapat menebak kapan ada perubahan baru padaProduct
sehingga harus meminta data baru secara berkala agarSubscriber
terus memiliki perubahan terbaru.
Explain what will happen to the program if we decide to not use multi-threading in the notification process.
- Setiap
product_type
dapat memiliki banyakSubscriber
. Jika kita tidak menggunakan multi-threading untuk proses notifikasi, ini akan menjadikan proses notifikasi memakan waktu yang sangat lama dan memblokir proses lain untuk berjalan. Ini akan menyebabkan web app kita tidak dapat menghandle request lain selagi mengirimkan notifikasi keSubcriber
terkait. Tentu ini merupakan hal yang tidak diinginkan kita, oleh karena itu, multi-threading digunakan agar proses pengiriman notifikasi tidak memblokir proses lain untuk berjalan, sehingga web app kita masih dapat menghandle request lain.