These are chat archives for dry-rb/chat

8th
Aug 2016
Piotr Solnica
@solnic
Aug 08 2016 09:47
@timriley we need one global system instance man, can’t have it otherwise
Tim Riley
@timriley
Aug 08 2016 10:01
Yeah, you're right @solnic. Perhaps what we need instead is some way to make have an "uninitialized" state until it's been provided with the config, other deps it needs.
Piotr Solnica
@solnic
Aug 08 2016 10:13
@timriley got a second?
Tim Riley
@timriley
Aug 08 2016 10:19
@solnic I do now, yep
Piotr Solnica
@solnic
Aug 08 2016 10:21
@timriley what’s the case against class-based systems?
and what are the benefits of instance-based?
dealing with IM objects is always tricky (see rom initialization process) so we gotta make sure it’s worth the effort
Tim Riley
@timriley
Aug 08 2016 10:23
I was just thinking about the need to provide a system/component with config it would need
and any other “external” things that must be passed to it in order for it to function properly
that was the moment when I thought of instances
but I realise (as I mentioned earlier) that may not work out in practice
Piotr Solnica
@solnic
Aug 08 2016 10:24
my current gut feeling is that we should keep it as it is
Tim Riley
@timriley
Aug 08 2016 10:24
Yeah, I think that’d probably be wise.
Piotr Solnica
@solnic
Aug 08 2016 10:25
are there any actual issues with the global containers?
containers == systems
Tim Riley
@timriley
Aug 08 2016 10:26
No, no major issues. Just that I want to be able to “boot” any given system and have necessary config or external things passed to it.
Common example: sub-apps.
Right now, they reach right out to the umbrella’s top-level system to get at app config.
Piotr Solnica
@solnic
Aug 08 2016 10:26
hmm ok
Tim Riley
@timriley
Aug 08 2016 10:26
What should happen: the config necessary (and nothing more) for a sub-app is passed to it in some formal way.
And until that config is provided, the system is “uninitialized” or “not ready” in some kind of way.
Piotr Solnica
@solnic
Aug 08 2016 10:28
we have that concept, it’s called finalize
Tim Riley
@timriley
Aug 08 2016 10:28
Right. So perhaps we just need to build slightly more into what that offers.
Piotr Solnica
@solnic
Aug 08 2016 10:28
yep
having a sub-system knowing about top-level system seems bad, so I agree this should be done in a more elegant way
elegant == less coupling
@timriley could you point me to an example of this issue?
(that’s pre-Dry::Web::Settings, in a totally up-to-date app it’d be Berg::Contaner.settings.admin_mailer_from_email, but you get the point)
Ideally, it (a) wouldn’t reach out to get the setting from the umbrella, and (b) the setting name internally wouldn’t have to have the “admin” name in it. It’d just be mailer_from_email
Piotr Solnica
@solnic
Aug 08 2016 10:32
@timriley do you have any use case where something else than a config is needed?
Tim Riley
@timriley
Aug 08 2016 10:33
And the top-level umbrella would get it’s admin_mailer_from_email setting and pass it to the admin sub-app as mailer_from_email
Yeah. I’m not fully convinced that sub-apps e.g. importing the umbrella (so we can share the base rom container) is the right direction for doing things...
couldn’t the umbrella pass it’s ”persistence.rom” object to the sub-apps as a persistence object or something?
so all the sub-apps would say is “I need you to provide me with a persistence object before I can go to work”
however, I could see this meaning that more work has to be done to any sub-app system/container before you can e.g. test things in isolation
right now, because the sub-apps know to reach out an import e.g. Berg::Container, they’re a lot closer to being ready to work than if things had to be passed to them before they were ready
Piotr Solnica
@solnic
Aug 08 2016 10:38
@timriley we should have a way of saying “this system needs that”
ie use ‘core.persistence’
Tim Riley
@timriley
Aug 08 2016 10:39
Yeah
oh yeah, something else I found awkward
When building a class that needs a bootable dependency, I end up with something like this:
require "main/import"

# I don't really like how this has to be here...
MyApp::Container.boot! :mailchimp

module Main
  module Operations
    module SubscribeToNewsletter
      include Main::Import["core.mailchimp"]

      def call(attrs)
        # ...
      end
    end
  end
end
Having that top line doesn’t feel right
Again, it’s another case of Main sub-app telling MyApp to do something
Piotr Solnica
@solnic
Aug 08 2016 10:42
yeah, I thought about this a while ago, thinking that import should trigger booting
Tim Riley
@timriley
Aug 08 2016 10:42
All that’s in boot/mailchimp.rb is this:
require "mailchimp"

MyApp::Container.register "mailchimp", Mailchimp::API.new(MyApp::Container.settings.mailchimp_api_key)
Piotr Solnica
@solnic
Aug 08 2016 10:43
we know what needs booting, so if import sees that something hasn’t been booted yet and it was asked to load it, then we gotta boot it automatically
Tim Riley
@timriley
Aug 08 2016 10:44
I guess right now we have no way to know that “core.mailchimp” is actually a bootable dep
Then OTOH there are cases where code in sub-apps reach up into the umbrella namespace for the right reasons, i.e. with superclasses providing common behaviour
e.g.
require "berg/transactions"
require "main/container"

module Main
  class Transactions < Berg::Transactions
    configure do |config|
      config.container = Main::Container
    end
  end
end
but I think these are actually two different things
a shared app namespace vs an orchastrating umbrella system
Tim Riley
@timriley
Aug 08 2016 10:58
(Berg::Transactions could very well in this case by SomeOtherGem::Transactions)
the other thing to think about here would be how we mount/boot/initialize the web interface as a system itself
right now that isn’t handled in any formal way
Piotr Solnica
@solnic
Aug 08 2016 11:01
Is it needed?
Tim Riley
@timriley
Aug 08 2016 11:01
well, we configure the container from inside the Dry::Web::Roda::Application
Actually, that’s probably the right way :)
my bad
Piotr Solnica
@solnic
Aug 08 2016 11:01
:)
Piotr Solnica
@solnic
Aug 08 2016 11:17
@timriley we should be able to figure out which component needs booting by looking at boot paths and searching for a file that matches component’s identifier, no?
Tim Riley
@timriley
Aug 08 2016 11:22
if the component’s identifier matches a file path, yeah
common exceptions are in things like bootable deps, or “external” things like “core.persistence”
Piotr Solnica
@solnic
Aug 08 2016 11:31
@timriley dry-rb/dry-component#26
I’d like to get that merged and then open PRs with a couple of improvements, sounds good?
timriley @timriley looks
Tim Riley
@timriley
Aug 08 2016 11:38
Sounds good.
Piotr Solnica
@solnic
Aug 08 2016 12:34
@timriley dry-rb/dry-component#27
dis is rather naive, but works ;)
Tim Riley
@timriley
Aug 08 2016 12:38
Good start :) will look more closely tomorrow!
Piotr Solnica
@solnic
Aug 08 2016 12:46
@timriley could you give me access to Berg? I’ll push a branch with some stuff for you to see, don’t want to fork it
Tim Riley
@timriley
Aug 08 2016 12:51
@solnic sure thing, one sec!
@solnic done
Piotr Solnica
@solnic
Aug 08 2016 12:52
@timriley thanks
@timriley looks like it’s a bit behind with other stuff
still uses result-matcher
etc
Tim Riley
@timriley
Aug 08 2016 12:59
Yeah. It's not perfectly up to date.
Piotr Solnica
@solnic
Aug 08 2016 13:06
huh ok not enough time to update all the stuff with kleisli and matcher extensions
Piotr Solnica
@solnic
Aug 08 2016 13:12
@timriley anyhow, things are booting in berg correctly
@timriley are there any cases like you mentioned before where you refer to umbrella container from a sub-app to boot something manually?
I can’t find it, fwiw
Tim Riley
@timriley
Aug 08 2016 13:21
Not in berg, I don't think
That example I pasted before was from the project you worked on with us at Icelab :)
Piotr Solnica
@solnic
Aug 08 2016 13:24
@timriley damn, I thought it was in berg, well at least you’re half-way there with upgrading to dry-system :D
Tim Riley
@timriley
Aug 08 2016 13:26
Heh, yep. I'll check things out tomorrow! Gnight:)
Actually, tbh it is probably an issue in berg too
Anything that uses postmark
We probably just haven't added the explicit Berg::Container.boot! :postmark lines in the right places
Fran Worley
@fran-worley
Aug 08 2016 13:56
@solnic is there a way to pass message options into a message_set?
Piotr Solnica
@solnic
Aug 08 2016 13:58
@fran-worley don’t remember O_o
check sources :)
Fran Worley
@fran-worley
Aug 08 2016 14:01
@solnic will do :)
Looks like it's not going to work the way I was hoping. Once we have simplified the errors_ast can we chat about the errors api as we've got a number of reform issues that I can't fix the way it works currently
Piotr Solnica
@solnic
Aug 08 2016 14:10
@fran-worley yeah we gotta do it
I’ll have some extra time tomorrow/Wed so I’ll try to at least start working on it
Fran Worley
@fran-worley
Aug 08 2016 14:12
cool. I'm around tomorrow so should be able to lend a brain.
Sergey Kukunin
@Kukunin
Aug 08 2016 18:07
hello guys. I have one off-topic quesiton, but since dry-rb inspires me a lot, and I'm sure you all know the answer, I'm going to ask. I'm building new Domain layer in my application from scratch, and want to choose the best approaches for it (because now is the best time to pick right approaches)
so, I want to implement 'never have object in illegal state' as well as immutability
but I'm not sure, how can I implement them all. For example, DDD says about Entities with them own states, but I want to have everything immutable (is it good idea). Is it still possible?
also, how do I create object. I don't like 'everything in hash' constructor, because it reduces explicity of object (again, by DDD). Is it good idea to accept only mandatory arguments in constructor, and set the rest optional attributes via setters (which will copy object on every setter property)?
Piotr Solnica
@solnic
Aug 08 2016 18:29
@Kukunin I removed “creating objects” from my vocabulary, so I just store/update data instead, and use separate object types for reading data
Sergey Kukunin
@Kukunin
Aug 08 2016 18:31
@solnic that makes sense. object shouldn't know how to create itself. but with immutability, you need to return modified copy on every data change, so setter needs to know, how to make copy with update attribute
Piotr Solnica
@solnic
Aug 08 2016 18:33
yeah I don’t do that, a system receives data, optionally transforms it, and stores in the db, so ie I don’t create intermediate objects to represent a changed object, this concept just doesn’t exist, in rom-rb we just added Changeset API for that, but it doesn’t require changing actual objects, it’s all about the data and that’s it
Sergey Kukunin
@Kukunin
Aug 08 2016 18:36
hmm. does it mean, that this approach isn't compatible with DDD?
like, it is db-driven model, not object-driven
Sergey Kukunin
@Kukunin
Aug 08 2016 18:42
actually, it can be done, with introducing some data-objects. Like immutable object in domain layer has some data-object he can deal with, and implementation of data-object is somewhere in infrastructure layer
or just hash in memory
this article is pretty for this kind of separation: http://www.yegor256.com/2014/12/09/immutable-object-state-and-behavior.html. But that's weird: immutable objects relies on mutable data-storage
Piotr Solnica
@solnic
Aug 08 2016 21:13
it is weird, that's why I don't do it anymore
separating reading from writing has been a great improvement for me
re DDD, not sure what you mean with compatibility with DDD
Sergey Kukunin
@Kukunin
Aug 08 2016 22:55
anyway, I've watched this talk https://skillsmatter.com/skillscasts/4971-domain-driven-design-with-scott-wlaschin about functional programming types (as I understand, what dry-types tries to achieve) and really likes it. That's like totally another world
regret a little bit, that ruby isn't type safe language