Live data from Hacker News

Better Software Design with Clean Architecture

fullstackmark.com

61–70 of 141 posts

Re: Better Software Design with Clean Architecture

#61
post #2

At what point should basic validation be completed?

There is no easy answer here. Where and when validation happens requires some careful analysis.

I find it helps a lot to think carefully about (1) message validation -- is this a valid message? (2) entity validation -- is this entity in a valid state? and (3) enterprise validation -- is the business system as a whole now in a valid state? These three questions map on to what is often an ACL, domain, and domain services layer. At the end of the day there's going to be corner cases though in which case as a rule of thumb there's something to be said for doing validation at the edges and moving it in closing to the center as needed. In my experience when it's not clear where validation belongs that often means nobody really understands that validation (or that validation is even wrong and is not what the business wants -- it happens!) and so there's something to be said for keeping it out of the core domain.

Re: Better Software Design with Clean Architecture

#62
post #33
post #31

This design puts entities in the middle - everything else pivots around entities. Additionally, it uses the OO approach of implementing logic as methods on the entities. After a couple of decades of experience, I've come to the conclusion that this isn't right. Most business rules involve processes, which are inherently procedural, or, from another perspective, functional - functions of the whole state of the system…

This is solved by DDD and aggregates. Here's how i would do it. Course - Aggregate Root Student - Aggregate Root RegisteredCourses[RegisteredCourse[]) - Sub Entity Collection - with id reference to course. With metadata like date time when the registration occurred. RegisterForCouse Method There should be no mutable public properties, internal methods should be private. Everything should go through an aggregate root…

Thank you for mention this. I was hoping that someone mention this. Usually DDD solves this issues because of the rules in the construction of the Domain Models. I usually identify entity != domain models... Entity is the representation of the storage units and domain models goes beyond that by including domain rules....

Re: Better Software Design with Clean Architecture

#63

Oh look, more kludgy over-designed enterprise gumf. When are people going to learn that if you just start with the entry point with granular components, letting each define the interface for its dependencies, you get a much nicer, looser, more flexible structure than these enterprise "patterns" that ultimately all just turn into a big ball of mud? Stop pretending you can design codebases.

Which is essentially what this is.

Re: Better Software Design with Clean Architecture

#64

Oh look, more kludgy over-designed enterprise gumf. When are people going to learn that if you just start with the entry point with granular components, letting each define the interface for its dependencies, you get a much nicer, looser, more flexible structure than these enterprise "patterns" that ultimately all just turn into a big ball of mud? Stop pretending you can design codebases.

This plus checking codebase in regular intervals for: * KISS? * Bundled components? * Dependency injection useful? * Duplicated components / functions? * Too much/less abstract classes? Interfaces useful?

In my case that looks like: Write code for 6h, review and refactor code 2h. Result is that less code is produced (due to refactoring/removing/etc.) and codebase keeps being simple. On the other hand it's easier to write tests.

No need to use complex enterprise patterns. Most of time simple facades and delegators are enough. Consider writing small simple components instead of using heavy patterns with a lot of boilerplate code.

Re: Better Software Design with Clean Architecture

#65
Oh god no. DON'T POLLUTE THE CURRENCY.

This is a massive fuck up and it won't scale or be modular. The idea is fine but you need the entities/currency into a smaller core with your DAL and relationship objects above that layer. The only functions your currency should have are accessors or read-only convenience calculations. Other operations should be handled by another parent because let me tell you that that Course collection is going to end up being null or empty A LOT when it "shouldn't" be.

You'll want your use cases to return shallow object graphs (e.g. GetCourses => courses.Enrolled => StudentName, StudentId) from the data layer/services and then if you want to look up a Students details you make that another call. The alternative is to run some sort of "scope" object that defines the depth of graph you want when accessing a general api. The thing you're looking to avoid though is returning more information than is necessary.

Also who taught this guy to model? Students are in courses in this model the courses are inside students and that's silly.

Re: Better Software Design with Clean Architecture

#66
post #59
post #57

Earlier quoted context omitted.

If I say "students can be registered for courses in the school" then you might think the OO model should be school.register(student, course) which does actually seem reasonable to me. Here the school object would basically be the system's logic as a whole, and both the course and the student could just be IDs. I really think single dispatch OO is a huge distraction and I haven't seen any strong arguments for its use…

Nothing about DDD says you can't use multi-dispatch. If this how you think about the problem. Then this is your solution if your language is capable of expressing it.

Yeah, I'm quite a big fan of Eric Evans and DDD. Especially the more high level parts about ubiquitous language, bounded contexts, anti-corruption layers, and many of the other patterns. Yet I think that the focus on single-dispatch OO kind of dates the book and makes it less general and beautiful, much like how the GoF's "Design Patterns" book is more banal than Christopher Alexander's work on pattern languages because of the overemphasis on specific implementations of single dispatch OO patterns (the notorious visitor pattern, for example).

Re: Better Software Design with Clean Architecture

#67
post #33
post #31

This design puts entities in the middle - everything else pivots around entities. Additionally, it uses the OO approach of implementing logic as methods on the entities. After a couple of decades of experience, I've come to the conclusion that this isn't right. Most business rules involve processes, which are inherently procedural, or, from another perspective, functional - functions of the whole state of the system…

This is solved by DDD and aggregates. Here's how i would do it. Course - Aggregate Root Student - Aggregate Root RegisteredCourses[RegisteredCourse[]) - Sub Entity Collection - with id reference to course. With metadata like date time when the registration occurred. RegisterForCouse Method There should be no mutable public properties, internal methods should be private. Everything should go through an aggregate root…

CourseRegistration.Register(course, student);

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.

Re: Better Software Design with Clean Architecture

#68
post #56
post #32

Which language is he using? Is that C#? It looks like this only deals with in-memory data structures. How does stuff get read from / written to the DB?

Actually, very similar, since Entity Framework is usually used. Sources implement the IQueriable interface which lets you write queries with method chaining or LINQ. To be honest, it kinda looks better than it is. In reality I find it produces sub-optimum performance and a lot of things can not be done without spilling query logic to the app. Not to mention a lot of linq/method chaining queries cannot be translated t…

You can persist this model using anything you want.

You would have some kind adapter/library that handles the persistence.

It would take these models, and covert them into your datastore.

Re: Better Software Design with Clean Architecture

#69
post #33

Earlier quoted context omitted.

This is solved by DDD and aggregates. Here's how i would do it. Course - Aggregate Root Student - Aggregate Root RegisteredCourses[RegisteredCourse[]) - Sub Entity Collection - with id reference to course. With metadata like date time when the registration occurred. RegisterForCouse Method There should be no mutable public properties, internal methods should be private. Everything should go through an aggregate root…

CourseRegistration.Register(course, student); 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.

In this case it isn't that bad since its only loading registered courses for that specific student. Which for a student would be limited(10?). In fact it should probably be a business rule inside RegisterForCourse that a student can only register for a specific amount of courses per semester.

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.

Re: Better Software Design with Clean Architecture

#70
post #57
post #47

Earlier quoted context omitted.

"students can be registered for course" - This is already implying an order.

If I say "students can be registered for courses in the school" then you might think the OO model should be school.register(student, course) which does actually seem reasonable to me. Here the school object would basically be the system's logic as a whole, and both the course and the student could just be IDs. I really think single dispatch OO is a huge distraction and I haven't seen any strong arguments for its use…

If the pairings of courses and students are registered in the school object, then that's basically OO implementation of a many to many relationship of students and courses.

That's why I like Django. You just tell it that you want a many-to-many between students and courses and it does they for you, symmetrically, without forcing you to introduce a class such as "school".

Post reply on HN