You normally need load an entire aggregate, so that you can maintain your invariants. If you separate into 3 aggregates such as Course, Student, CourseRegisteration then starts to become harder to maintain business rules. For example if you wanted the RegisterForCourse method to limit student course registration to 10, it would now have perform another query.
If start doing queries that don't match up your domain model, then should probably do CQRS. Which would allow you to build a model optimized for queries.
One day someone is going to want slightly different rules for student course registration and then they'll realise this rule is baked into the core and that's sad.
This is a desirable trait, and one of the main points of DDD. If you want to change registration, you change the core business logic. It then applies to all applications using that business logic. If you have a real business case for different registration methods, then you simply model that on your entities.
If you don't do this, your going to get business rules applied inconsistently as programmers will interpret requirements slightly differently.
So what's easier to change? Giving customers versions that give them all different types of the core base type Student or JUST changing the type of CourseRegistration that they visit? (CourseRegistration is a service as opposed to a currency).
You keep your currency CLEAN.
If you want something radically different, then are you even developing the same application anymore?
By the way i've never heard anyone call the core entities of an application "Currency" before, where did you even learn that? I imagine that could be confusing.
I also imagine having an application where you have build custom methods for each customer who wants something slightly different is terrible for codebase maintainability.
I make a career out coming to companies that should have (according to you) made radically different systems but didn't. Most companies don't find it economically justifiable to re-write based on slightly different customer requirements and most companies have many deployments, not just "one perfect one" that most modellers appear to imagine. If your design doesn't have the flexibility of change designed into it you're going to struggle when you get a second client.
> I also imagine having an application where you have build custom methods for each customer who wants something slightly different is terrible for codebase maintainability.
Yeah of course its a massive pain in the ass but it enables you to sell more.
Then don't. Make the domain model customisable with various options.
Having specific methods for specific companies seems a lot worse.
I build SAAS applications which have various customization options customers can do. I don't really have a problem with it. I've designed a clean way to customise.
I made the same mistakes as OP and learnt the hard way. I encourage you to explore a greater purity in your models in the future because I genuinely believe it leads to better code.
CourseRegistration.ViewCoursesFor(student);
I think giving either entity "ownership" of the relation is a disaster waiting to happen. I just have this vision of someone wanting data about students accidentally loading all the course information. In the DAL of course you end up modelling however but seeing courses in a student just makes me ill.