Documentation

Things I would do differently next time

As this project is set up to experiment there are a few things I've tried that, while not terrible (otherwise I would've already refactored them away), I'm still not 100% happy about.

A separate auth and user context

The goal of this project is to play with domain-driven design, and as such, I wanted a project with several bounded contexts to play with. So I created a separate auth- and user context.

Now, if you have external authentication this would make sense. I do not however, so this just adds complixity without much benefit. For a next time I'd say just merge the two into a single bounded context.

Authentication via JSON web tokens in a cookie

I tried authenticating via JWTs in order to have a stateless web application. Aside from the database of course. Oh, and bits of caching or other in-memory state. ... Right.

But aside from the fact that draughts is far from stateless anyway, this is also silly because JSON web tokens are meant to be short lived. And that doesn't match with a web app where you want to log in once from your personal computer, and then stay logged in for a year. To make it workable my JWTs are valid for a day, which may be fine for demo purposes, but really isn't ok in production. Both because this is way to long for a JWT to be secure, and way to short for user convenience.

The reason using a JWT like this is insecure is because you cannot invalidate a token, and so you cannot log out. There are workarounds for that of course, but these require server-sided state, which kind off defeats the purpose... So yeah, I'll just use ye olde boring session cookies next time.

Overusing application services

The domain-driven design architecture recommends application services to mediate between your controllers and your database. And so I dutifully added them everywhere.

I ended up refactoring a lot of them away however, because most of the time there's little or nothing at all for them to do that a controller can't just do itself. There's a few left that have some use, but I think you can skip application services most of the time.

Specifications

The specification pattern is a cute little pattern that you can use to deduplicate domain logic and where logic in database queries. You can also use it to chain together many different query predicates.

And while that's nice and all, I don't actually use much of that. So for draughts this adds a layer of abstraction that has little value. Best scrap 'em next time.

Seperate transactions for each event domain

In draughts I have separate database users for each domain, and they can't update data for another domain. Which is how it should be.

This does mean however that when I need to retroactively sync or resend events I need to start and commit transactions from one domain to the next and then back agian. I kind of like this because that's also how it'd had to happen if these events are really sent accross different applications. That said, in draughts they aren't and I can just cheat and create a database user that can access all databases and be done in one go. Maybe a bit of a hack, but it'd be much easier. Hmmmmm.