C
C#2mo ago
0xHati

Chess Game API project structure

Hi, I'm fairly new to c# and .net. As a way to learn I'm making a chess game api, which will be consumed by a frontend to implement the UI. I'm using EF with postgres to store the game state of each game. The structure is roughly something like this: game class with general props as if the game is still playing, who's turn it it. It's responsible for initiating the Board object The board class has a list of squares, each square can have a piece on it. The board class inits both the squares and places the pieces on the squares, according to the starting position. I have an abstract class Piece, which all individual pieces inherit, the pieces have individual logic about if a move is valid yes or no. Now I have two questions: 1. In most examples I see online the Models are POCO objects, with no extra functions, calculations or anything. It just maps the database tables. In my case I have a board class for example and it has logic inside it. Is this ok, or what is the proper way to set this up so I have lean models and put the logic elsewhere? Is this in the 'service layer'? I'm confused between all the different architectures such as ddd, onion, clean architecture, etc. I suppose I can have a BoardModel and a BoardLogic, but they would almost have the same properties except for an Id. If I want to simplify the response object to the api I would also end up with a BoardDTO. This would mean 3 classes and might be overengineneering for the what I need. Still having the model together with the logic feels not clear either. 2. What's the proper way to make the API restfull, eg. I can't use and endpoint game/{id}/makeMove since that's an action which isn't restfull so I've read. Would it be game/{id}/moves/add ? Although it's more understandable the addmove, I suppose the second is more in line with the standards. Thanks for helping, Hati
5 Replies
Angius
Angius2mo ago
1. You would detach the database models from your actual pawn classes, yes. The database would store, for example, only the square coordinates and pawn type Then you would do something like
var state = await _context.Boards
.Where(b => b.Id == id)
.Select(b => new BoardDto {
Name = b.Name,
// ...
Pieces = b.Pieces
})
.FirstOrDefaultAsync();

foreach (var piece in state.Pieces)
{
var p = piece.Type switch {
PieceTypes.Pawn => new Pawn(),
PieceTypes.Rook => new Rook(),
// ...
}
board.Place(piece.X, piece.Y, p);
}
var state = await _context.Boards
.Where(b => b.Id == id)
.Select(b => new BoardDto {
Name = b.Name,
// ...
Pieces = b.Pieces
})
.FirstOrDefaultAsync();

foreach (var piece in state.Pieces)
{
var p = piece.Type switch {
PieceTypes.Pawn => new Pawn(),
PieceTypes.Rook => new Rook(),
// ...
}
board.Place(piece.X, piece.Y, p);
}
to restore the state of the board 2. Don't sweat restfulness
0xHati
0xHati2mo ago
So in this case the dto is the model object? Or how would the folder structure look like?
Angius
Angius2mo ago
Generally, you would have three kinds of objects: 1. Database models, which would be dumb POCOs 2. Game objects, which would have whatever functionality needed 3. DTOs for requests and response, which would again be dumb POCOs
0xHati
0xHati2mo ago
Thank you, appreciate it a lot. This seems a good approach, though it also feels like overkill to have 3 similar classes that (in this case) are almost the same.
Tvde1
Tvde12mo ago
I'd prefer GET or POST /games/123/moves