"Do you really need a database?"

I wonder, perhaps, if you are misinterpreting something that I perceive as a main theme of Phoenix 1.3.

I gather that in Ruby on Rails, there is a tendency for the persistence mechanism (ActiveRecord) to pervade an application in a way that the logic of the domain model that the application operates on becomes entangled with the persistence code. As a result, I have been lead to believe that it is common when writing an Rails App to begin solving any problem by figuring out how you are going to squeeze that problem into the database. (as with most things, probably true in some cases and untrue in many)

I gather from the 1.3 presentation, that for various reasons (one of which was the generated code that Phoenix produced) some Phoenix 1.2 apps started to show this unhealthy trait of the persistence driving the domain model of a problem. As I understand it, one of the main aims of Phoenix 1.3 is to help developers keep a healthy separation between their domain modeling code and the code used to persist elements of that model.

In that case the warning is “Don’t start solving your problem by designing your database”. Start by creating code that models your domain and solves the problem. Then, if you need to persist data, find a way to do that. A database might be one good choice among many.

5 Likes

DB, no DB. Uncle Bob has much to say about that:

http://blog.cleancoder.com/uncle-bob/2016/01/04/ALittleArchitecture.html

And:

https://8thlight.com/blog/uncle-bob/2012/05/15/NODB.html

6 Likes

@gwww Great articles!

Like really liked the “6 Commandments of Architecture”

  1. Woe is the architect who prematurely decides on a database, and then finds that flat files would have been sufficient.

  2. Woe is the architect who prematurely decides upon a web-server, only to find that all the team really needed was a simple socket interface.
    
  3. Woe is the team whose architects prematurely impose a framework upon them, only to find that the framework provides powers they don’t need and adds constraints they can’t live with.
    
  4. Blessed is the team whose architects have provided the means by which all these decisions can be deferred until there is enough information to make them.
    
  5. Blessed is the team whose architects have so isolated them from slow and resource hungry IO devices and frameworks that they can create fast and lightweight test environments.
    
  6. Blessed is the team whose architects care about what really matters, and defer those things that don’t.
5 Likes

@easco, Thanks for clearing that up.

In that case the warning is “Don’t start solving your problem by designing your database”

I’m starting to get the essence of the idea.

Reading Unlce Bob’s articles linked by @gwww also helped.

@easco, have you by any chance read Functional Web Development with Elixir, OTP, and Phoenix by @lance?

As far as I can see the approach in the book does exactly what @sasajuric “warns about” in To spawn, or not to spawn?

Would anyone like to comment on that?

I’m now at the point where I’d like to implement my homebrewing app as a Elixir-only app first and only when that is done I’ll decide on persistance and web interface.

But I’m still having difficulties modeling the buisness logic and I feel like I’m getting conflicting advice :expressionless:

This is addressed here and in the few following posts: Functional Web Development with Elixir, OTP, and Phoenix (Pragprog) - #60 by mjadczak

2 Likes

@LostKobrakai, thanks

@redrapids
Lance and I are working with some great reviewers to make sure we address this feedback. We’re going to shift the approach for the two chapters in question, the chapter on modeling and the chapter on wrapping the result in OTP.

As a popular book in the community, we want to make sure that the guidance we give is sound.

This sounds fantastic! Now We just have to wait for the changes :slight_smile:

1 Like

Yes I did read it and. I noticed that. As others pointed out there was a thread of discussion on the topic.

I’m a homebrewer myself perhaps if you posted some details of your model folks could help you place bits and pieces.

I think it’s good to have some perspective outside of some fairly exotic scenarios you really do want a database. You are very unlikely to be able to have a performant alternative at reasonable cost outside of fairly niche scenarios.

@andre1sk
I think it’s good to have some perspective outside of some fairly exotic scenarios you really do want a database. You are very unlikely to be able to have a performant alternative at reasonable cost outside of fairly niche scenarios.

Yeah, that’s what I was thinking. And really still think. But I would love to be proven wrong.

And I think that the point of “you don’t need a database. Databases are not your friends”-vibe is more a “Don’t design a database and put an application on top of it. Design your app and use whatever presistance makes sense for the app. If any”

– as far as I’ve gathered anyways

1 Like

I’ll try doing that. Thanks for suggesting it.

So I guess I’ll just post it here and see what happens…

Basically users have recipes
a recipe have a yest_profile, malt_profile, mash_schedule, hop_profile and adjuncts
a batch will have a recipe, brew_date and other batch spekecific data points
I’m thinking that there should be both public and private repositories for malts, yeasts and hops

I have some other features in mind, but let’s leave that out for now.

If I was to “go the Uncle Bob way” and leave persistence out of this for as long as possible, how would I do this?

1 Like

I think the ‘contexts’ that Phoenix 1.3 is introducing are very much in line with the “create an interface for your app’s business domain and implement it for the persistence piece(s) you are considering.”, in that the context module is the only place where the business domain layer and the technical layer meet.

yeah. I agree. But I’m too much a noob to take all of this stuff in in one go…

I guess what I’m struggling with is see nice pure functions and modules for this use case.

My mind is in object <-> Database land…

Take malt_profile. It would have a name and some attributes like colour and such. I can’t imagine that cramming stuff like this in an Agent or Process would have any benefits.

There’s no real time commutation going on. The only thing a malt would ever do is being a part of a malt_profile. And that in turn, would only be part of a recipe, which would be part of a batch.

No game dynamics. No chat. Nothing fancy (yet)

I agree with you. There doesn’t really seem to be any reason to put those things into an Agent or process in-of-themselves. They could just as easily be crammed in a struct:

defmodule StrangeBrew.MaltProfile do
  defstruct name: "", base_malt: :two_row, specialty_malts: [], lovibond: 100 # etc

  def to_string(profile), do: "#{profile.name}(#{profile.lovibond}˚L)")
end

By the same token there’s not any particular reason to start out by tying them to a database. In the future, should you want to try some fancy stuff (say estimating Lovibond from the particular grains in the profile) you shouldn’t have to “contaminate” your estimation logic with a bunch of stuff related to database queries and the size of table columns.

1 Like

Thanks again.

That’s actually what I started doing yesterday. With one eye on “To spawn or not to spawn” and one eye on the Functional Web Dev book I began making modules with structs to represent my contexts/units. Let’s see where this leads :+1:t2:

1 Like

Don’t forget, Kernel.put_in/3 is your friend when doing nested structs :slight_smile:

(and the only reason that I’m mentioning this is that I had a hard time finding it in the docs when I needed it…)

1 Like

Thanks!

I am reading the same book(functional-web-development-with-elixir-otp-and-phoenix) and this exactly what I am feeling like recently. Initially I was really excited because I feel like it can be a huge performance gain since there is no more back and forth between code/logic and database.

I also ask some questions regarding my specific need on elixir-lang IRC. The specific conversation can be found here beginning 4:06PM between users yial2(myself), @radar, and Zarathu. The preliminary is that GenServer process may not be suitable for my need, but I am still doing some more reading to try to find out more on my own.