#grouping types in shared/

1 messages · Page 1 of 1 (latest)

atomic ocean
#
// shared/src/shared.gleam
import gleam/time/timestamp.{type Timestamp}

pub type ApiErrorCode {
  InvalidFormCode
  InternalError
}

pub type ApiError {
  ApiError(code: ApiErrorCode, message: String)
}

pub type Signup {
  Signup(email: String, name: String, password: String)
}

pub type User {
  User(
    id: Int,
    email: String,
    name: String,
    password_hash: String,
    created_at: Timestamp,
    updated_at: Timestamp,
  )
}

do you guys think that grouping shared types together is a valid case of not grouping by domain?

#

the functions cannot be shared because server and client call their own respective functions for each type (encode vs decode, etc)

#

i mean they can be shared but only one side would use them

#

the alternative would be to just redefine the types on both sides, which im not entirely opposed to, this just seems more organized

atomic ocean
#

i guess another downside to shared types that im seeing is that they cant be opaque

#

but i feel like thats fine since my logic is centered around 2-3 main files anyways

#

everything is working pretty well so far

uncut silo
#

Types being shared doesn't sound bad but there's a couple of things I'd be wary of:

  • sharing types in a third shared project is good. Though grouping them all under a types.gleam/shared.gleam is still an antipattern to me. Things shouldn't be grouped by what language construct they are
  • the advantage of sharing types between frontend and backend (that's what I'm guessing you're doing) tends to be a bit overblown in my opinion. Usually you end up in a situation where both sides need something slightly different and you have to end up in a worst-of-both-worlds situation where the type definition has to accomodate both needs and you end up transmitting more data than necessary
tight pawn
uncut silo
#

Yeah exactly! Very different needs

atomic ocean
#

If im going to commit to separate representations

#

I guess for the rare case where the rep is identical, but at that point might as well stay consistent with separating

trail epoch
#

If I find myself wanting the same types I typically go with message passing like lustre does - loosely following Elm architecture. Then the shared type is just a message and each side can decide how to handle it and represent the data itself independently

tight pawn
trail epoch
# tight pawn Can you provide for me a tiny example. It’s hard for me to see what you mean as ...

For example, I just wrote an electron app for internal use at work. It's a dashboard that has a scratchpad, and pulls user's assigned jira tickets and crawls part of the file system for any vscode workspaces they have.
Since javascript runs both the front end and back end, it seems like shared types would work, but for safety the front end can only call functions that are explicitly exposed.
So it sends messages like "REFRESH_JIRA_ITEMS" and the backend will do the jira api call. When it's done, it passes the data to the front end in JSON format with a message like "JIRA_ITEM_RETURN" so that the front end can take the data and know what it's for.
But the JiraItem type isn't shared, since it's just a front end construct for displaying.
When you double click a jira item, it sends a message to the back end "LAUNCH_JIRA".
Node gets the jira item (DEV-1234) and constructs the link and launches chrome to the link.

tight pawn