Clojurians
#clojure
<
2016-02-28
>

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

noisesmith00:02:54

mpenet: boorad: awesome, thanks for the input

boorad04:02:31

can’t say enough about the db… they seemed to have gotten transactions correct, and AQL is a good doc/graph query language

john.care10:02:23

I’ve just started with emacs and cider. Out of the box expand-region seems to have no shortcut assigned. does cider use something different for structural selection?

mostr12:02:10

what do people use to do authentication/authorization in clojure these days? I see friend and buddy being quite popular choices. Any personal recommendations?

rauh13:02:37

@mostr: I'm just integrating buddy. I like it A LOT. Great docs. Simple api.

mostr13:02:19

yeah, looks like it’s way better documented than friend is, which is kind of important to newbie :simple_smile:

amacdougall16:02:18

Friend seems to do more things for you—I like that it has integrated OAuth workflows, to bounce the user to Facebook/whatever for login. I just couldn't figure out how to use it for my API-request-only auth. I'm sure it's not actually hard, I just couldn't load it into my brain. Buddy, on the other hand, was a snap. Granted, I cribbed heavily from http://luminusweb.net/docs/security.md.

munen16:02:55

Hello everyone I’ve been struggling the last 2 hours to get a(ny) HugSQL statement running. I’m using Conman and Migratus to connect and configure a Postgres DB. Postgres seems to be configured correctly, since lein run migrate works. However executing any generated form from HugSQL results in an IllegalArgumentExeption with db-spec mount.core DerefableState is missing a required parameter. I have run out of ideas what that parameter might be and where to fix it. Can you guys help me out with a hint, please?

dm317:02:49

@munen - could you post the code, please?

munen17:02:35

@dm3: I have just realised that the problem only exists within lein repl and the Emacs Cider Repl. I didn’t bother to check in the web app served by lein run. Pasting all code would be too much, but I’m getting the same error when just trying the example Luminus Guestbook application. There all code is most likely properly set up and I’m still getting the same error in the REPL: https://github.com/luminus-framework/guestbook

nonrecursive19:02:35

@mostr another +1 for buddy

hiredman19:02:28

munen: that error is very much like the one clojure.java.jdbc throws is you pass the wrong thing in for it's "db spec" parameter, where 'mount.core' seems like the wrong thing being passed in, are you passing a symbol in to java.jdbc somewhere?

hiredman19:02:24

you should pastebin your stacktrace

martinklepsch19:02:44

Why does assoc-in not support more than 3 args similar to assoc?

echristopherson20:02:18

@john.care: cider uses paredit for structural stuff

munen20:02:31

@hiredman: I’m leaving the facilitation of the actual connection to Conman which in turn refers to mount.core. I’m not directly communicating with jdbc.2 My Code looks very similar to this: https://github.com/luminus-framework/conman#defining-queries

hiredman20:02:07

munen: very similar doesn't count for much, you should pastebin the stackstrace

munen20:02:26

@hiredman: Interesting enough, I have realised by now that the actual code works fine when run in lein run. It’s just lein repl and Cider Emacs that do not work. Which is kind of unfortunate.

munen20:02:40

@hiredman: Since it works in lein run, I think it’s probably less about the code then some environmental issues. But I’d gladly pastebin the stacktrace. Mom.

munen20:02:29

One moment(;

munen20:02:20

This is the trace I’m getting for all HugSQL forms. My guess is that it wants an explicit connection passed in.

hiredman20:02:22

it looks like slack ate part of the exception message you shared earlier

hiredman20:02:45

`db-spec mount.core.DerefableState@2bcf2439 is missing a required parameter``

alexmiller20:02:58

@martinklepsch: there's a ticket for that http://dev.clojure.org/jira/browse/CLJ-1771

hiredman20:02:46

some an instance of mounte.core.DererableState is being passed in to clojure.java.jdbc as a db-spec

martinklepsch20:02:48

@alexmiller: neat, should've checked :simple_smile:

hiredman20:02:27

mount is a sort of component like system, right? so mount.core.DerefableState must a component, so somewhere you have a component that contains a db-spec, and instead of pulling the db-spec out and passing to the database code (hugsql or java.jdbc) you are passing the component in

clintm20:02:32

Do any of you know how, or is it not possible in clojure by design, to expand a symbol to a function name? Example: (defmacro x [func & args] (pkg/@func @args))`

clintm20:02:49

oops… formatting. :stuck_out_tongue:

clintm20:02:25

Oh, maybe it’s a symbol vs. value issue.

munen20:02:01

hiredman: Thank you for your help! You are certainly right in that the wrong thing is passed in. However, I do not get why there should be anything passed in at all. I’ve been stuck for 6 hours without fix and it’s getting late. I’ll try some sleep before getting back to it. The help is much appreciated!

hiredman20:02:39

munen line 30 of issue_tracker/db/core.clj

munen20:02:10

hiredman: Oh my, I have a solution! If I manually execute (mount/start #'issue-tracker.db.core/*db*), then I can start HugSQL queries like (db/get-user {:id "1”}). Still.. I can find no mention of this need in the docs. You brought me on the right track for a manual solution, though. That’s good enough for now. It’s much appreciated, thanks!

alexmiller20:02:01

@clintm: you probably want 'resolve'

tolitius21:02:05

@munen: take a look at (try) the mounted luminus guestbook branch: https://github.com/luminus-framework/guestbook/tree/mounted it should work without you manually starting db, it should make it to the release/master soon

hiredman21:02:53

I just don't understand why people use mount, I must be missing something, its model of each namespace as a component, with state as a global thing in a namespace(maybe I am mistunderstanding this), just seems bad, like sticking (def state (atom {})) in every namespace would be

yogthos21:02:25

@hiredman: could you elaborate on the actual problem you see there?

yogthos22:02:04

note that mount doesn't tie the functions in your namespace to the state in any way

yogthos22:02:10

you can still use a protocol with it if you like

yogthos22:02:26

all it does is track the lifecycle of stateful variables

hiredman22:02:41

global state variables, right?

hiredman22:02:11

you can only have a single instance of these state variables per clojure runtime, and it is visible to any and all clojure code, right?

yogthos22:02:21

yes, what is the problem with that

yogthos22:02:34

if I have a database, I necessarily have a single instance of that database

hiredman22:02:45

but that isn't a database

yogthos22:02:46

this goes for pretty much any external resource

hiredman22:02:51

that is a connection to a database

yogthos22:02:05

and there's still precisely one connection per database

hiredman22:02:11

and there are plenty of reasons you might want more than one connection to what ends up being the same database

yogthos22:02:17

could you name one

yogthos22:02:41

I see no reason why you wouldn't want to centralize code that accesses an external resource

hiredman22:02:15

you structure your app in such a way as to have to logically distinct databases, eahc having their own "connection" but in production your ops team decides to use one database

hiredman22:02:33

I've seen that happen multiple times

yogthos22:02:41

and how is this at odds with mount?

yogthos22:02:53

you create a defstate per connection instance

yogthos22:02:59

and it manages that connection instance

yogthos22:02:10

either you have one connection defined in your app, or you have multiple

hiredman22:02:11

if you want to test running a cluster of your server, if you don't use global state you can run multiple copies in the same jvm, with global state you cannot

yogthos22:02:24

you would have to explicitly write your app to use multiple connections

yogthos22:02:38

why would you need to run tests on the same jvm

yogthos22:02:51

is there a repl shortage that we're experiencing?

yogthos22:02:05

this is the only argument I've ever heard against the mount approach

hiredman22:02:40

writing a deftest that runs multiple jvms is way more involved

yogthos22:02:54

that's not what I meant

hiredman22:02:11

I am kind of surprised, are you seriously argueing that global state in an app is a good thing?

yogthos22:02:13

I meant that you should use lein profiles to specify a separate configuration for your test profile

yogthos22:02:30

the actual code in the application should be environment agnostic

hiredman22:02:37

like you have no problem with code that does (def foo (atom {})) everywhere?

yogthos22:02:59

you still haven't provided a concrete example of a problem

yogthos22:02:18

so if you have a problem with the mount approach, then could you please articulate it

yogthos22:02:06

the problem with global state is generally that it ends up being being difficult to track in the application

yogthos22:02:17

however, this is not what happens when you use mount

hiredman22:02:22

it is hard to articulate an objection to something that I think flies in the face of functional programming since the invention of lexical scope

hiredman22:02:43

if something is global, it isn't scaoped

yogthos22:02:51

so basically you're saying that you dislike it for dogmatic reasons

hiredman22:02:59

it cannot be local, you cannot have your own copy

yogthos22:02:27

passing your state around in a global var that's referenced everywhere as you do with component isn't any different conceptually

hiredman22:02:36

no, I mean, I have used and worked on systems that didn't have a way for different parts to keep state outside of (def foo (atom {})) and it was terrible

yogthos22:02:51

in fact I've seen it make things far more problematic, because now your entire app depends on the state being available

hiredman22:02:03

writing large test suites, ok, which bits of global state where need to be written and set up for this test

yogthos22:02:21

but majority of your application should be stateless by design

yogthos22:02:37

the whole point of using a functional language is that you only deal with state at the edges of your application

yogthos22:02:57

mount allows you to represent stateful resources and provide an API for them

yogthos22:02:12

but those are predominantly dealing with IO, and have no actual business logic in them

yogthos22:02:42

with mount, you don't need your external resources for testing vast majority of the time

yogthos22:02:39

yet, I've seen many component based applications where state was passed around all over the place as the system map

yogthos22:02:55

and none of the application could be tested without external resources being available

hiredman22:02:29

at my last job, our largest codebase, predated component, mount, whatever, and it was largely written as just a bunch of namespaces, and if they needed state the had to use some kind of global mutable thing. whenever the opportunity for a new project came up, no one chose to do that again

hiredman22:02:47

sure, nothing guarantees automatic correctness

yogthos22:02:05

you still have to be mindful of your design whatever approach you take

yogthos22:02:23

and just because you saw a mess with global vars, doesn't mean global vars were the inherent problem

yogthos22:02:40

same as if I saw a mess made with component, it's not necessarily component that's at fault

yogthos22:02:03

however, if you understand why global state should be isolated then you can do that equally easily with both monut and component

yogthos22:02:11

and neither is a substitute for that understanding

donaldball22:02:53

If I can’t run multiple instances of my system in the same jvm, I think that’s a design problem

yogthos22:02:15

I have yet to see a practical use case for that

yogthos22:02:30

this pattern seems to be specific to the reloaded workflow

hiredman22:02:34

I am not saying global vars are a problem, clojure vars are global, I am saying a global atom is bad

hiredman22:02:48

I have never used the reloaded workflow

yogthos22:02:25

my experience is that having a namespace that represents the resource is a very clean way to isolate stateful components

hiredman22:02:37

but I have definitely written tests, where I wanted to observe how multiple instances of a server interacted together

yogthos22:02:27

and I still think it's much cleaner to run each instance in its own jvm

yogthos22:02:51

but that's the tradeoff you make

yogthos22:02:56

both options are available

yogthos22:02:31

however, you said that you don't understand why people use mount, and I'm explaining my rationale for using it :simple_smile:

hiredman22:02:56

there are trade offs right, depending on whatever, running each an its own jvm may be cleaner, but is that fast enough to run as part of your regular test run, how painful is it to maintain the clojure.test code to do that

yogthos22:02:30

I find that I don't need to access resource for majority my tests

yogthos22:02:40

because I structure my apps to be predominantly resource agnostic

yogthos22:02:49

in most cases I'm testing the business logic

yogthos22:02:57

I'm not testing my database or the database connection

hiredman22:02:59

yogthos: yeah, I am just kind of shocked, like if I saw code in a code review that had (def foo (atom {})) in it, I would require a lot of explaining

hiredman22:02:15

mount seems no different, and it is getting built in to stuff

yogthos22:02:16

in fact I would argue that if you need access to resource to run mosts tests, that's a problem with the deisgn

yogthos22:02:41

I think the conceptual model for mount is very simple

yogthos22:02:57

you have a resource and you have an API for accessing it

yogthos22:02:11

to me it makes perfect sense to use a namespace to abstract that

yogthos22:02:25

furthermore this helps provide real abstractions over the resource

yogthos22:02:29

what if its nature changes

yogthos22:02:38

I might be using a database today, and switch to using a service tomorrow

yogthos22:02:55

the rest of the application shouldn't be aware of the details of where the data comes from

hiredman22:02:12

right, that is exactly the argument for lexical scope

hiredman22:02:22

direct passing of parameters, etc

yogthos22:02:25

I don't see how that's the case

yogthos22:02:39

if you pass parameters from your business logic, you've coupled your business logic to the resource

yogthos22:02:41

that's a bad thing

hiredman22:02:45

I need an A, I don't know where A is, someone just passes me one

hiredman22:02:10

and if fact the person that passes me an A, maybe have 100 different As to choose from, or may just create and destroy one on the spot

yogthos22:02:17

I'd much rather have a shallow layer that deals with IO that sits around the core business logic that's resource agnostic

yogthos22:02:25

again, you have to actively structure your application to isolate stateful code

yogthos22:02:34

and mount doesn't make it any more difficult

hiredman22:02:55

sure, but code that takes parameters is by definition less coupled than code that doesn't

yogthos22:02:21

the only limitation is that you can't run multiple instances inside the same jvm, if that's a requirement then mount is a bad fit, if it's not then it's perfectly fine

yogthos22:02:41

I've been working with Clojure for about 6 years now, and I haven't seen that be a requirement yet however

yogthos22:02:15

right and in my case business logic takes data as a paremeter

yogthos22:02:22

it is inherently decoupled from the resources

tolitius22:02:25

@hiredman, @donaldball: > if you want to test running a cluster of your server.. > if I can’t run multiple instances of my system in the same jvm, I think that’s a design problem > it cannot be local, you cannot have your own copy.. in those rare cases (the only one I know of is "running tests in the same dev REPL") you *can*: https://github.com/tolitius/yurt but learning how people use mount, I see that there is no shortage of REPLs in that one use case. besides, running something like boot watch speak test in another REPL is great regardless of whether you using mount or whatever

hiredman22:02:38

but isn't this just piling complexity (managing multiple clojure runtimes) on as a bandaid to a problem you wouldn't have to start with, with out global state?

ghadi22:02:47

ding ding ding

ghadi22:02:04

I like it when arguments are provided (outside in), not discovered (inside reaching out)

yogthos22:02:07

it's a problem most people don't have though

ghadi22:02:18

you have the argument anyways, whether you see it or not

ghadi22:02:37

the db is an argument to a subsystem that accesses the db

yogthos22:02:55

I see the db as a separate component from my business logic

yogthos22:02:08

my view is that you should be able to take the business logic and package it as a library

ghadi22:02:10

i think that's optimistic in a lot of cases

yogthos22:02:13

if you can't then your system is coupled

yogthos22:02:38

I haven't found this to be problematic myself

ghadi22:02:59

¯\(ツ)

yogthos22:02:08

and that's why we have different people using different things

hiredman22:02:26

https://gist.github.com/hiredman/27733 is the earliest clojure code of mine I could find, from 7 years ago, anything earlier is likely lost to lisppaste

yogthos22:02:34

there isn't one true way to write applications

yogthos22:02:04

that's a slippery slope fallacy though

ghadi22:02:20

I will make another fallacy --

yogthos22:02:28

I don't think anybody will argue that you can't make a mess with mutable state

yogthos22:02:30

of course you can

yogthos22:02:44

saying that because you can make a mess all state is bad is a stretch

yogthos22:02:05

and I don't see how coupling your business logic to your resources makes the problem any better

ghadi22:02:23

I've lived a war story of trying to remove Korma (sql) from a system over a year or so... I'm afraid mount will lead to similar situations, because the root cause (ambient global state) is the same

yogthos22:02:27

you still have global state for all intents and purposes, and now you can't even test anything without it

hiredman22:02:42

yogthos: you have been argueing against coupling business logic to resources, but no one was said you should

yogthos22:02:57

yet that's what I commonly see with component

yogthos22:02:06

and not just component in fact

yogthos22:02:19

if you look at other DI approaches, this is quite common

yogthos22:02:30

you have a singleton that gets passed around all over the app

hiredman22:02:42

but that is a false dichotomy, right?

hiredman22:02:02

just because you see it in component, doesn't mean you don't see it in mount

yogthos22:02:05

so is saying that mount = (atom {})

yogthos22:02:23

yet you've made that analogy a couple of times here :simple_smile:

hiredman22:02:33

yogthos: false equivalence

hiredman22:02:45

(is I think what you mean there)

hiredman22:02:00

is defstate global mutable state?

ghadi22:02:12

hint: defstate

yogthos22:02:17

of course it is

yogthos22:02:27

does it mean that it will make your app into a giant mess magically

yogthos22:02:29

of course not

yogthos22:02:55

if you use monut or component, you're going to have to structure your app in a very similar way to avoid this problem

donaldball22:02:13

Huh, that’s not been my experience with component either. The various fns that require (probably protocol implementing) arguments get them explicitly, not the whole system blob.

yogthos22:02:30

but where do they get them from?

yogthos22:02:38

they have to be passed in from somewhere

yogthos22:02:47

since you're not keeping any global state, you have to pass it around

yogthos22:02:01

so now parts of the application that shouldn't care about the state have to take it as a parameter

hiredman22:02:05

that is just not correct

ghadi22:02:09

yeah that isn't

donaldball22:02:25

In my case, a ring handler component got refs to the components needed by the various app handlers and injected them into the requests

hiredman22:02:49

when you create a component system, you tell it about the dependencies between components, and each component only has access to the bits you say it needs

yogthos22:02:06

yeah your system has to be accessible though

ghadi22:02:12

no it doesn't

hiredman22:02:25

to the individual components? no it doesn't

yogthos22:02:32

parts of it do

ghadi22:02:46

lots of people make the system accessible as part of the "reloaded" workflow, but it absolutely is not that way in a prod deployment

yogthos22:02:23

look, your app initializes, it creates the system then resources in that system have to become available to functions that use them

yogthos22:02:30

there is no way around that

yogthos22:02:44

now you can either keep that interaction at the edges of your app

hiredman22:02:58

yogthos: right, and the way that happens is, you explicitly tell component when creating the system, which components need each other

yogthos22:02:06

it's same with mount and component

ghadi22:02:09

components reaching their grubby little hands to find some piece of shared state that they didn't tell you that they needed initially is the problem

yogthos22:02:15

that's not the problem I'm talking about

yogthos22:02:49

I'm saying that if you have a piece of business logic and it has to accept any stateful variable as a parameter because it calls a function that uses it then you've got coupling

yogthos22:02:26

I'm also saying that plenty of systems using component do precisely that in the wild

yogthos22:02:41

and I would go as far as to say that component encourages this approach by design

ghadi22:02:49

I want some sort of limits/bounds on the parameters to a subsystem. I hate having to use something that has interactions beyond where it should

ghadi22:02:00

Having explicit arguments helps with ^

yogthos22:02:01

in fact examples of that can even be seen in presentations on component

ghadi22:02:09

people are so frigging lazy

hiredman22:02:15

if you have a piece of busines logic that has to use some state, but you reading it from a global place instead of passing it in, you've got even more coupling

ghadi22:02:20

i don't want the DB parameter passed around

yogthos22:02:36

@hiredman: my whole point is that business logic should never need state

ghadi22:02:37

-- said people who were bitten later

yogthos22:02:40

pretty much by definition I would say

yogthos22:02:52

you should always be able to deal with external resources at the edges

yogthos22:02:07

and if you aren't then I'd say that's a problem

yogthos22:02:27

business logic should operate on the data

ghadi22:02:40

i can get behind that as a generalization

yogthos22:02:53

I'm a little surprised that this is controversial somehow

ghadi22:02:02

specifically, mount doesn't support you in realizing that

yogthos22:02:13

so if we agree that business logic should be state agnostic

yogthos22:02:28

mount doesn't only support it, it encourages this

ghadi22:02:41

let's write code

yogthos22:02:47

let's write code

ghadi22:02:21

what would be a simple example?

yogthos22:02:36

let's say we have a service operation to authenticate a user

yogthos22:02:41

the user comes from the database

yogthos22:02:52

we accept a request, get user info, authenticate

yogthos22:02:00

I would treat authentication as the business logic

yogthos22:02:22

while the code that talks to the client and the database would be the IO layer

yogthos22:02:31

does that sound like a reasonable distinction?

ghadi22:02:16

seems reasonable, but it depends on where exactly that line is drawn

ghadi22:02:24

say more about authentication?

yogthos22:02:14

so with mount I might write code like this

yogthos22:02:34

parts that care about the state are the POST handler and the db

ghadi22:02:42

k i don't like that right away =(

yogthos22:02:47

that's fine

yogthos22:02:59

I do though

yogthos22:02:04

and that's what counts to me :simple_smile:

ghadi22:02:25

Fair enough :wink: I was thinking authentication should know nothing about where it comes from

yogthos22:02:30

only parts that care about IO are the POST route and the database namespace

yogthos22:02:39

once I got the data, that gets passed to the core of the app

yogthos22:02:52

and the core of the application doesn't care one bit where it came from or where it goes

ghadi22:02:52

(defprotocol IAuthenticator (authenticate [_ user]))

yogthos22:02:58

it doesn't

ghadi22:02:04

it knows it comes from the db

yogthos22:02:08

all it knows is that it got a map

ghadi22:02:10

not from an LDAP service

yogthos22:02:10

no it doesn't

yogthos22:02:28

I pass the user value to the authenticate method

ghadi22:02:28

ok, which part is the map?

yogthos22:02:38

that's the map returned from the database

yogthos22:02:50

by the db/get-user method

yogthos22:02:04

the database API is effectively getters and setters

yogthos22:02:07

there's no logic

yogthos22:02:19

the POST handler also doesn't have any logic

yogthos22:02:26

this is the layer I'm talking about

yogthos22:02:54

you can think of it as serialization/deserialization of data from external resources

ghadi22:02:55

how do you test this?

yogthos22:02:12

I can test authenticate by passing it a mock user record

yogthos22:02:20

I don't need any access to resources to do that

yogthos22:02:35

I can do end to end tests by providing a test resource

yogthos22:02:40

but I would do that very rarely

ghadi23:02:06

is authenticate a pure function?

yogthos23:02:09

I tend to run full tests before I commit code and on the build server

yogthos23:02:13

absolutely

yogthos23:02:23

it takes data and it returns data

yogthos23:02:31

it's not aware of any state or resources

ghadi23:02:53

you can test authenticate, how do you test the whole route?

ghadi23:02:17

it's not so obvious

yogthos23:02:47

the route would require a test resource for testing

ghadi23:02:54

in the db?

yogthos23:02:58

I would test it in a separate repl with a test profile

yogthos23:02:17

but as I pointed out already, my experience is that I need to do this kind of testing rarely

ghadi23:02:20

where are your pure functions now

yogthos23:02:35

precisely because I don't keep business logic in the layer that deals with the IO

yogthos23:02:47

in my business logic

yogthos23:02:03

the thing that's the lions share of the application

ghadi23:02:38

if you want to vary multiple implementations of components together -- I've found component to be very useful. Sometimes the components have to be a level up from typical logic (e.g. UserStore vs Database)

yogthos23:02:52

so how is this at odds with mount?

yogthos23:02:59

you can create a protocol say for a queue

yogthos23:02:13

then initialize instances of the protocol each with its own state

ghadi23:02:23

different vars?

yogthos23:02:48

if I have two different queues, they're conceptually two separate resources are they not?

yogthos23:02:01

by their very definition

ghadi23:02:21

oh I meant different implementations of the same resource

ghadi23:02:25

sorry confusing

ghadi23:02:32

not separate resources

yogthos23:02:41

what is an example of that

ghadi23:02:58

Like LDAPUserStore vs DBUserStore

yogthos23:02:13

you'd write two separate implementations of that wouldn't you

yogthos23:02:27

each would be a separate namespace

ghadi23:02:41

yes -- how do I instruct the subsystem that consumes a UserStore as to which one it should use?

yogthos23:02:55

I would be explicit about that

ghadi23:02:13

binding vars?

yogthos23:02:16

you're not going to be randomly switching between what store you use

yogthos23:02:34

so then can you give a concrete scenario

ghadi23:02:57

test vs normal

yogthos23:02:10

then I'd provide a different resource in the profile

yogthos23:02:25

but why would I test against two completely different types of resoruces?

yogthos23:02:31

that seems like a recipe for disaster to me

yogthos23:02:46

if my app goes to ldap in production, I would surely want to use the same mock api in tests

ghadi23:02:01

sometimes it's the same impl, but a variant. For example, fault injection

yogthos23:02:30

let's put it this way, your worst case scenario with mount would be your best case scenario with component

ghadi23:02:32

you test that a slow network is handled properly with timeouts

yogthos23:02:41

you'd create a protocol and a record that wraps whatever states you want

yogthos23:02:06

you'd still retain the same api for the resource in that case

yogthos23:02:16

mock resources should have same api as the real resources

ghadi23:02:27

but you have to know which internal resource to mock in that case

yogthos23:02:37

if I had a mock connection in my defstate then it should behave like a real one right?

yogthos23:02:53

what's an internal resource by the way?

ghadi23:02:38

you have to know how a subsystem works intimately, to be able to mock it effectively (with mount)

ghadi23:02:05

that problem is gone by design with component

yogthos23:02:12

I disagree

ghadi23:02:12

which is an important distinction

yogthos23:02:24

in fact sounds like you're setting yourself up for a bigger problem

yogthos23:02:39

since you don't know how your system works, you can end up with bugs around the edge cases

yogthos23:02:47

I certainly wouldn't advocate such an approach

yogthos23:02:15

if you have a mock of a resource that doesn't exactly match how the real one works, that's extremely problematic in my opinion

ghadi23:02:04

the ability to cleanly interchange means you've designed good interface

yogthos23:02:26

but what does that have to do with mount?

yogthos23:02:35

if I have a database connection managed by deftate

yogthos23:02:42

its interface is the API that I implement

yogthos23:02:44

that's the resource

ghadi23:02:49

reaching for resources rather than taking your arguments

yogthos23:02:03

I think we're going in circles here

yogthos23:02:18

we already covered this point earlier, with examples to boot

yogthos23:02:11

if you prefer the way component works, it's there and nobody is asking you not to use it

yogthos23:02:26

but there's absolutely nothing wrong with using mount either

yogthos23:02:41

it's a personal preference, and different people like different things

yogthos23:02:55

but I have yet to see a coherent argument against using mount

ghadi23:02:14

It's clear we disagree (still), but I'm happy to have had the discussion!

yogthos23:02:10

same here :simple_smile:

yogthos23:02:05

I don't think it's wrong to disagree, a lot of things come down to tradeoffs, and different apps have different needs

yogthos23:02:12

there's no silver bullet for this

yogthos23:02:24

having options is a good thing in my opinion

yogthos23:02:25

I find that people tend to have different preferences based on their experiences and the way they like to approach problems, and it's always good to have these kinds of discussions to get a broader view of things