Live data from Hacker News

Better Software Design with Clean Architecture

fullstackmark.com

131–140 of 141 posts

Re: Better Software Design with Clean Architecture

#132
post #60

Earlier quoted context omitted.

"You pay for those boundaries with a convoluted mess of classes that describe the design pattern rather than the business logic. You end up with AbstractRequestInterfaceFactory type stuff." I disagree. If a design (call it an architecture) is clean and coherent, it's obvious. Because obviously a client must send the order to a server, which is protected by a gateway. And of course that gatway validates the client req…

> Simple, no? what happens when the business rule clashes with the database's constraint implementation, because different people either misinterpreted, or due to incompetence or miscommunication? I think splitting up sounds great in theory, but in practise, has lots of pitfalls. That's not to say it's not a good idea, but one musn't look at it with rose-tinted glasses.

Well you'd test, which would catch that scenario. Assuming you're not testing and discover it after releasing to production you'd just use your change process.

Either way this is just part of building a system. Refector, re-test and release (or re-release). It's hardly going to be the only bug you find.

Re: Better Software Design with Clean Architecture

#133

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…

For shallow vs deep, what I decided for my code base was that I'd pick the appropriate depth as a general rule for an object and not worry about I/O micromanagement.

If it is cheap to pull the additional data and it makes sense to expect that data in using the object, I'd simply embed the representation. If it was expensive or not commonly used, I'd include a reference to the data (usually ID(s) of the data).

Then in the repository, I'd just get everything necessary to return a full object as designated.

An onion architecture gets funky if you don't know if the object you are working with has all its data, especially because the object itself shouldn't know how to fetch more data about itself.

In this particular case, the two objects probably shouldn't have ANY domain connection, and there should just be a method on the course repository to "GetCoursesForStudent" that accepts a student ID. It's perfectly ok to model relationships in the database that don't have parallel relationships in the domain objects.

Or, one could create a "SemesterEnrollment" object that contains a student object and a collection of courses. Which would probably make more sense, as that's the object that should be referenced to generate bills, report cards, etc.

Re: Better Software Design with Clean Architecture

#134
As a teenager I would sit in the offices of grey haired old men at the software company I had no business working for after dropping out of high school. These men would hand me a photocopy of an OOPSLA paper, or something from a journal. I was told to read it, then come back and discuss. This was my intro to many areas of software architecture.

I became familiar with the names of people like Booch, Rumbaugh, Jacobson and others. Over the years I learned various object oriented programming languages and patterns. Each new thing was like discovering a horcrux, at first magical and powerful, but ultimately evil. Later I began to learn functional programming and that's what I try to use most these days but it too has its promises and lies. I have built and helped others reason about many many complex systems and all I can say is this:

The only system that is well ordered internally is the one that accreted complexity in increments, and was continually refactored along the way. Best practices be damned.

Those systems might not look how you'd design them were you Uncle Bob. They work, can be understood, and can be modified without much consternation. We all can recite examples of masterpiece turned morass. Conversely some of us can recite an example of a frog, a weird complex beast but ultimately very well adapted to its environment and quite resilient. Frogs are not beautiful but great at eating bugs.

One fact of complex systems is: humans cannot know the "right" design until AFTER he has arrived at it.

If a human can know the design a priori then the problem is NOT COMPLEX and if it is not complex then it is not modern software.

This is humbling knowledge for someone who wants to believe there can be a language and pattern of order for all systems. One that can be expressed in anything less precise than code itself.

Given a fanciful machine that could assemble subatomic particles in any fashion the user desires none of us could, having never seen one, design a frog.

Re: Better Software Design with Clean Architecture

#135

Earlier quoted context omitted.

People forgot at some point that design patterns are for solving problems. The key being that you should only be solving problems you actually have, and stop making up imaginary problems in your head before you even start coding. My code is typically some dumb data objects, static functions to apply rules to that data, and a bunch of interfaces for abstracting external dependencies. The code that ties everything toge…

What kind of design is this? Is there a name for it? I'd like to read more (both out of interest and being skeptical of how this scales)

I should come up with some catchy name and a blog post for it. It's basically my own custom mix of procedural (entry points), functional (static validations), and design by contract (external abstractions) in the noun worlds of Java and C#. I arrived at it after seeing too many instances of:

* Architecture / design pattern lasagna, where breaking through abstraction layers felt like Inception. And adding a data field meant going through all 5 layers of code...

* Inheritance for functionality instead of typing.

* Also, breaking Liskov substitution willy nilly then wondering why things are hard to reason about. (Because your code becomes entirely reliant on the types actually present at runtime, since you can't rely on semantic equivalence.)

* Tacking methods into data objects because that's where the data is. See other comments on this post advocating a "register" function on the Student object, or should it be on the Course class... Answer is neither. Encapsulation is about maintaining invariants. It's not about putting all functions related to students in the Student class.

* Zero unit tests because external dependencies weren't isolated and all the logic is hard coded into exact use cases, which eventually end in hard coded external dependencies...

Re: Better Software Design with Clean Architecture

#136

Earlier quoted context omitted.

People forgot at some point that design patterns are for solving problems. The key being that you should only be solving problems you actually have, and stop making up imaginary problems in your head before you even start coding. My code is typically some dumb data objects, static functions to apply rules to that data, and a bunch of interfaces for abstracting external dependencies. The code that ties everything toge…

What are the disadvantages?

A great question. Honestly it's a very natural fit for me, so I'm probably not very well qualified to answer.

There can be a lot of code repetition. To me, that's not a bad thing. I've seen people to themselves in knots trying to DRY some common code, just to later have to undo it all because a requirement changed for only one of the code paths. And, as I said, I like my procedures to read like use cases.

I'll see if I can think of anything else...

Re: Better Software Design with Clean Architecture

#137
post #43
post #36

Earlier quoted context omitted.

How did you decide that the registration is a property of the student and not the course?

Registration is definitely not a property of the student. It's always a good idea in these situations to appeal to real life. The actual business will point the way of the business simulation. In the real world we don't ask students to register for a course. Instead students ask the Registrar to register for a course. When the Registrar makes her decision she considers far more than just the internal state of the Stu…

You nailed why I think many object oriented designs fall flat. People presuppose both that the objects within their domain encompass all objects (just students and courses) as well as that the objects within a domain will not change.

When #1 is missed I usually see that theres a design that doesn't mimic its domain and thus lose the ability for developers and users to have clear, concise communication. At that point OO is a disservice.

When #2 is missed you end up with IFilteredCourseAdapterProcessor as people attempt to bolt on components to solve future needs.

The addition of the "Registrar" to the domain immediately demonstrates how the naive interpretation is missing core components and I bet the users and devs fundamentally aren't speaking the same language.

This, imo, leads to conversations like, "Of course so and so approves all the registrations! Otherwise it would be madness!"

Re: Better Software Design with Clean Architecture

#138
post #87

Earlier quoted context omitted.

This guy has been thinking about this properly.

Take this thinking to the end and realize that it leads to freestanding functions. In general all the context of the program is needed to execute a functionality. It's not like the registration office owns all the students. It's not like a registration wouldn't change the student's context. Students are both an independent and related concept. The proper object to call most things on is a "Global" object. Now instead…

I like the simplicity of this. If the app is of appreciable size, do_some_thing depends on databases, webservers, external processes, filesystems and configuration. How do you test/debug/explore its functionality without setting all of that up?

Re: Better Software Design with Clean Architecture

#139
post #92

Earlier quoted context omitted.

Unfortunately no :(

Oh wow. I can't be sure, but I'm pretty sure I'm the engineer at Pivotal that you paired with. I definitely remember you making reference to homoiconicity in lisp when we were pairing the day that Clean Architecture really clicked in your head. It was a really cool moment. There's a lot of engineers at Pivotal, and we have a lot of projects, so maybe I can prove I worked on that codebase by referencing obscure detail…

Yes, it was you! Nice to reconnect :)

Re: Better Software Design with Clean Architecture

#140

Earlier quoted context omitted.

Take this thinking to the end and realize that it leads to freestanding functions. In general all the context of the program is needed to execute a functionality. It's not like the registration office owns all the students. It's not like a registration wouldn't change the student's context. Students are both an independent and related concept. The proper object to call most things on is a "Global" object. Now instead…

I like the simplicity of this. If the app is of appreciable size, do_some_thing depends on databases, webservers, external processes, filesystems and configuration. How do you test/debug/explore its functionality without setting all of that up?

I would actually say these all make good "objects", i.e. isolated pieces. On the other hand, no runtime polymorphism is needed. To avoid OOP at a syntactic level, what do you think of the following?

- For tests at a smaller level, decompose the application such that most parts are easily testable in isolation (without external "hard" dependencies).

- For mid-sized tests with external dependencies but mostly unidirectional dataflow, setup a global virtual table with all the mock methods (and instances) that are needed. Alternatively, traditional linking methods.

- For larger "integration" tests there is no substitute to testing the real thing. At some scale and level of interactivity with the database, you just have to talk to the true filesystem, the true database etc. You can still setup a test instance for most cases where there is no interaction with external services.

Post reply on HN