Crow is a centralized microblogging and networking platform that allows users to connect and post short blog material. Its emphasis is simplicity, and privacy.
The project was developed as part of our university course "Special Topics in Software Engineering" and is licensed under GPLv3.
During the development of this project, we will be using a private access Kanban Board using Trello.
- zoumas | Lead Backend
- doktorupnos | Lead Frontend - UI/UX
- marios-pz | Frontend - DevOps
Decoupled RESTful web service and a SPA front end.
The backend is being developed in Go, chosen for its simplicity and efficiency.
The communication with the Postgres Database is done via ORM. GORM is Go's most popular ORM and it was used solery for that reason. If we had a choice, we would go with a Database First approach using goose as a migration tools and a SQL compiler like sqlc. Although as it turned out, GORM's automigration came in handy for integration tests with testcontainters.
An example:
Under the user
package, the model user.User
is defined. An interface user.Repo
declares all the methods a type must implement in order to be used as a user.Repo
. Then in the database layer a type named GormUserRepo
implements user.Repo
. GormUserRepo
encapsulates the database communication but does is not aware of any business logic.
Finally, the business logic is implemented by a type named user.Service
.
It is worth noting that user.Service
doesn't depend on a specific data source, it could be a database, a message broker or a KINESIS stream. Or a in memory structure making it easy to test via mocking.
Go offers great support for Dependency Injection with its flexible interfaces.
To implement the restriction of the assignment that Dependency Injection must be used, the Repository Pattern was deployed.
The Repository pattern allows for the decoupling of the data from the business logic and the controllers. It also aids the 3 Layer restriction.
Authentication middleware makes up for DRY code.
Basic password authentication was used in the POST /api/login
and DELETE /api/users
endpoints.
While JWT access tokens are used across the majority of the API to handle safe access to resources.
Initially integration testing was done by connecting to a local Postgres database. This approach is cumbersome. A new developer needs to setup the database according to a special configuration in order to just run tests.
Then, we used docker compose. However this came with its own problems. Port collisions, stale data, lack of automation, race conditions. These problems results in flaky tests.
We concluded to use testcontainters. We can achieve indempotent behavior while testing what matters against real services.
The web-app interface is built using the Next.js React framework. No external CSS frameworks are used in the final UI design.
Most of the icons used are taken directly from Bootstrap Icons.