Skip to content

GlobalWebIndex Engineering Challenge#41

Open
gtopal wants to merge 6 commits into
GlobalWebIndex:mainfrom
gtopal:main
Open

GlobalWebIndex Engineering Challenge#41
gtopal wants to merge 6 commits into
GlobalWebIndex:mainfrom
gtopal:main

Conversation

@gtopal

@gtopal gtopal commented Sep 11, 2025

Copy link
Copy Markdown

Description

My deliverable for the GlobalWebIndex Engineering Challenge

@alexandros-georgantas alexandros-georgantas left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @gtopal 👋 ,

Thanks for taking the time working on this assignment!
Your implementation is complete and straight forward covering various aspects.
I have posted some comments in your PR more as a conversation starter.
To this end, I would appreciate if you find the time to have a look and address my comments!

Thanks,
Alex

Comment thread Dockerfile
@@ -0,0 +1,11 @@
# Start from the official Golang image
FROM golang:1.21-alpine AS builder

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please explain why you've used this specific version of Go?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This version is stable, lightweight and reduces the final image size. Moreover, I think it's preferable to use a specific version and not the latest in order not to break anything.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In principal I agree however this version if I am not mistaken is from 2023 https://go.dev/doc/devel/release#go1.21.0

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok! Next time I will be aware of not using an obsolete version

Comment thread collection.json
@@ -0,0 +1,175 @@
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice touch providing postman blueprint

Comment thread handlers.go
@@ -0,0 +1,298 @@
package main

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you were to provide a bit more structure to this deliverable how you will have done it?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sure some points need refactoring for readability and maintainability purposes.

I will:

  • Extract logic into functions:
    For example , the creation of the user could go in a seperate function
    or
    It could be useful also to create a seeder for creating users and assets related to the users and put an appropriate command also in Makefile
    Another example could be to create a function for starting the server

  • Create a .env.example and also a .env file to capture environmental variables
    For example I noticed that the variable jwtSecret could be stored in .env as JWT_SECRET

  • Create maybe a seperate folder for tests and put there seperate files for testing, one let's say for API calls and one for more general unit tests

  • Put the endpoint calls to a seperate file and the handling logic(functions) to another one.

Comment thread handlers.go
return assetID, true
}

func setupRoutes() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cloud you please provide an alternative for the structure of the favorites endpoints (to become more RESTful)?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes sure.

I know it will be better to structure my endpoints like below:

To add:POST /users/{user_id}/favourites
To update: PUT /users/{user_id}/favourites/{asset_id}
To delete: DELETE /users/{user_id}/favourites/{asset_id}
To list: GET /users/{user_id}/favourites

using request parameters like
http://localhost:8080/favourites/remove?asset_id=c217dd2d-1866-43f0-88a5-5550504fe62dis not a good practice

Comment thread handlers.go
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
user := store.GetUser(userID)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets say that someone asks to change from in-memory storage to a proper database approach. Based on this line, how easy is to make this transition?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if I understand correct, but I would change only the implementation of the GetUser
The method signature and usage stay the same. The receiver of GetUser would change to *DBStorage something like func (s *DBStorage) GetUser(id uuid.UUID) *User { ... }
and the implementation should query the DB.

In other words, I would take advantage of using interfaces in order based on my option to change the implementation based on the receiver.

Of course for the DB declaration I should create a service with an image let's say for Postgresql and define also the connection parameters to .env

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here basically I am more interested to hear your thoughts around D.I. and if it is feasible based on how you've implemented your handlers.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexandros-georgantas As it is , is not feasible cause I have a hard dependency on handlers

I have to define a more flexible approach such as declaring an interface like:

type UserStore interface {
    GetUser(id uuid.UUID) *User
}

and then make the handlers depend on UserStore

type Handler struct {
    Store UserStore
}

and injecting either an in-memory store or a DB-backed implementation.

Comment thread models.go
AudienceType = "audience"
)

type Asset interface {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

@gtopal

gtopal commented Sep 24, 2025

Copy link
Copy Markdown
Author

Hello @gtopal 👋 ,

Thanks for taking the time working on this assignment! Your implementation is complete and straight forward covering various aspects. I have posted some comments in your PR more as a conversation starter. To this end, I would appreciate if you find the time to have a look and address my comments!

Thanks, Alex

Hello @alexandros-georgantas ,

thanks for the feedback and your time looking my PR. I will reply as soon as possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants