<jhass>
yes, crystals metamodel is a bit different
<jhass>
@@vars don't have such an insane scope though, so you can use them
<BlaXpirit>
jhass, I basically want to initialize for a module
<BlaXpirit>
-for
<BlaXpirit>
mhm
<BlaXpirit>
I don't think @@ is the right thing
<jhass>
well, do you have class methods on the module and want to use instance vars in them or do you have instance vars and basically want to add to the class constructor your module is included into?
<jhass>
*instance methods
<BlaXpirit>
jhass, I want an instance var in a module
<jhass>
that doesn't answer my question
<BlaXpirit>
I have a module with methods that use an instance var
<jhass>
what kind of methods?
<jhass>
instance methods or class methods?
<BlaXpirit>
the instance var is module's own
<BlaXpirit>
and i want to use these instance methods on instance var
<jhass>
no, a module doesn't have instance vars in crystal
Ven has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
<a5i>
does Crystal encounter the diamond inheritance problem ?
colorados has quit [Ping timeout: 252 seconds]
<waterlink>
there is no multiple inheritance, so how can it?
<waterlink>
including multiple modules, I assume puts them in inheritance chain in the order of inclusion
<waterlink>
which means again, it is not a multiple inheritance => no diamond problem?
<a5i>
o
<a5i>
rite
<waterlink>
but still as with ruby modules still there is a problem of people confused, why their method didn't get called here
a5i has quit []
<waterlink>
because some module after module in the question have overridden this method
<waterlink>
Only if modules acted like traits
colorados has joined #crystal-lang
<waterlink>
when you need to explicitly resolve conflicts when multiple modules define the same method
a5i has joined #crystal-lang
<a5i>
waterlink: so a subclass cannot inherit the same methods and variables as 2 other classes?
<a5i>
only 1 other?
<a5i>
granted that the 2 classes are in no relation to each other
<waterlink>
subclass inherits only its direct superclass
<waterlink>
superclass inherits its own direct superclass
<waterlink>
and so on
<a5i>
why doesn't Crystal have multiple inheritance like Java? 'class Kid extends Person extends SoccerPlayer'
<waterlink>
why would you need it ?
<jhass>
>> class Parent; def a; :parent; end; end; module Mod; def a; {super, :module}; end; end; class Child < Parent; include Mod; def a; {super, :child}; end; end; Child.new.a
<DeBot>
jhass: attributes #1 = { noreturn }
<jhass>
mmmh :D
<a5i>
oh
<jhass>
anyway, it should say {{:parent, :module}, :child} or something
<a5i>
so instead of inheriting 2 classes, you inherit a class and includde a module ?
<waterlink>
I will not inherit at all as far as I can :)
<jhass>
including a module is inheritance though ;P
<waterlink>
If you were to ask me about importance of inheritance vs encapsulation vs polymorphism, and give me 100 points to distribute between them, I will come up with such answer
<waterlink>
Encapsulation 80, Polymorphism 40 and Inheritance -20
<a5i>
Rust has things like `struct Kid {...}; impl Person for Kid {...}; impl Human for Kid {...}`
<waterlink>
That is interfaces
<waterlink>
not an inheritance
<waterlink>
Whenever you inherit something, there is high chance, that composition (with delegation) would be better in long term
<a5i>
hm
<waterlink>
Because then you can use dependency injection =)
<waterlink>
And if you start putting your domain logic in modules and including it all over the place
<waterlink>
Then the codebase will become unmanageable in no time
<waterlink>
modules are good, if you put there some sort unrelated behavior, or some dsl capabilities
<waterlink>
and standard library modules are good, like Comparable for instance
<waterlink>
On the other hand
<a5i>
mh
<waterlink>
if you define inheritance as just inherit interface, but not its implementation..
<jhass>
modules can also be useful to break a really long class into multiple files until you can extract smaller classes out of it
<jhass>
(can = have time to)
<a5i>
but isnt that Rust version inheriting the Person and Human structs for Kid stuct?
<waterlink>
If you have really long class, then it violates SOLID principles
<waterlink>
no
<waterlink>
it implements Person interface for Kid and implements Human interface for Kid
<a5i>
o
<waterlink>
and even more, in Rust if you want to accept Kid as parameter to some method, you will get only methods from Kid on it. But if you want to accept Person as a parameter to some method, and pass in Kid, then it will act like Person, and Human interface will not interfere
<waterlink>
as far as I remember..
<waterlink>
Yeah, and again implementing multiple interfaces for one object/struct/record/whatever is already a code smell (because it obviously violates single responsibility principle)
<jhass>
depends on the interfaces
<jhass>
Comparable, Iterator, things like that I don't see as code smell
<waterlink>
Yes
<waterlink>
I told already, Comparable and Iterator are just useful abstractions
<waterlink>
They are good
<jhass>
or something that sets up associations to some common target, think include Commentable
<waterlink>
And this is not good )
DerisiveLogic has quit [Ping timeout: 252 seconds]
<jhass>
why not? should I rewrite Comment or the logic connecting to it for each object that I want to be commentable?
<waterlink>
instead of `class Post; include Commentable; end`, I would do: `Commentable.new(post)`
<jhass>
what's the concrete drawback of the former?
<waterlink>
Violating SOLID ?
<jhass>
how is an association doing that?
<jhass>
I do not copy functionality into the Post class, I DRY up setting up the association
<waterlink>
Ok, what if I want to have 2 different types of commentable and A/B test them on my production traffic ?
<waterlink>
With composition and dependency injection, I would just pass around a bunch of factories
<waterlink>
but with `include Commentable` I will have to do some weird things, or even put this logic right to Commentable module
<jhass>
I'd actually tend to prefer having the switching logic in Commentable over duplicating it all over the place on the caller side
<waterlink>
Duplicating?
<waterlink>
Why? My caller side will just do dependency injection of Factories. Once and for all
<jhass>
I'm not following your example I guess
<waterlink>
And this place of code will be an entry point to my application of course
<waterlink>
so no duplication
<jhass>
so you'd do ActualPost = Commentable.new(Post) or what?
<jhass>
so you do that each time you have a collection of posts
<waterlink>
Yes and no
<waterlink>
Here I have actual ability to just use post
<waterlink>
without any commentable functionality
<jhass>
say you display a user page with the posts authored by it and an aggregate of posts of users the current user is following
<waterlink>
because in current context I don't need it
<jhass>
you do A/B testing by determining in which group the current user is
<jhass>
how do you switch?
<jhass>
and where?
<waterlink>
post_finder.posts_of_user(user)
<waterlink>
post_finder dependency injected as something like PostFinder.new(ab_aware_commentable_factory)
<waterlink>
ab_aware_commentable_factory dependency injected as ABAware.new(user, CommentableFactory, NewCommentableFactory)
<jhass>
so now I have like what, 6?, classes I need to be aware of
<jhass>
opposed to 2 - 3
<waterlink>
No, you need to be aware only on site of dependency injection (1 site in the code)
<waterlink>
Everywhere in the code you work with instances that just implement certain interfaces
<waterlink>
More smaller classes is usually better )
<jhass>
I think this leads no where, I'm not following you and I think it's complicating an issue just for the sake of somebody said all your classes must follow some principle and you see it violated
<waterlink>
nope, not somebody said, I just have seen too much huge monolithic code..
<waterlink>
and `include SomethingRelatedToYourDomain` is the first thing to take its "technical debt" with huge interest rates
<jhass>
small classes is actually about code size and less about API, at least for me, I can easily not think about functionality that's included, I don't need to scroll over anything when reading the code using inheritance
<waterlink>
For me it is both
<waterlink>
almost always single responsibility principle maps to having one public API
<waterlink>
ie one method
<jhass>
and I don't need to know a ceremony of like 6 classes just to get a collection of posts
<waterlink>
everything else private/protected
<waterlink>
post_finder.posts_of_user(user)
<waterlink>
here you deal only with one object and one method
<jhass>
where does post_finder come from?
<waterlink>
it is dependency injected in current class as a parameter to new/initialize
<jhass>
who does that?
<waterlink>
class in the previous application layer
<jhass>
so likely me? sounds still like you just moved the ceremony elsewhere
<waterlink>
you, or any other developer on team, or someone who already not on the team
DerisiveLogic has joined #crystal-lang
<waterlink>
*on ~= in
<waterlink>
ok then
<jhass>
see, it's the kind I dislike about most Java APIs and frameworks you have to go through, the huge ceremonies you have to go though to get to a simple method you want to call
<jhass>
er, s/you have to go through//
<waterlink>
Yes, but if you look at any app of 100K+ SLOCs then you will see the problems that arise when you don't have such ceremonies
<waterlink>
Everything is so tightly couples
<waterlink>
*coupled
<waterlink>
To make a simple change to domain logic, you need to fix like 20 classes and 40 specs )
<waterlink>
because they directly depend on the thing you are changing
<waterlink>
If they were depending on it indirectly (ie through dependency injection), you could have just add new functionality just by adding new class and throwing it somewhere at the top of dependency injection chains
<jhass>
maybe I still have to gather experience there then, atm I do not see it as that much of a problem
<waterlink>
means 3 sites of changes instead of 60
<waterlink>
1 - new class, 1 - new spec and 1 - site of dependency injection
<waterlink>
It is all about being fast in the start and then being very-very slow after some years, or being a bit slower in the start, but maintaining the same speed over tens of years
<waterlink>
direct dependencies vs indirect (loosely coupled) dependencies
<waterlink>
respectively
ponga has quit [Quit: Leaving...]
<waterlink>
probably not 3, but 4 sites of changes: +1 integration spec
<waterlink>
And classes count bumps like crazy when doing things in that speed-maintaining manner, ie: from 70 classes of bad code to an equivalent code base of 1400 classes )
havenn is now known as havenwood
ismaelga has joined #crystal-lang
DerisiveLogic has quit [Ping timeout: 246 seconds]
<a5i>
can someone explain to me what the describe block does and what it's for?
<waterlink>
you mean:
<waterlink>
>> require 'spec'; describe String {}
<DeBot>
waterlink: Syntax error in eval:3: unterminated char literal
<waterlink>
And these description will be used as part of the failed example description
<waterlink>
ie, if this spec failed:
<waterlink>
Failure: User#save saves user record to data store
<waterlink>
it has its origin in RSpec (ruby testing framework) and they were inspired by BDD (behavior driven development)
<a5i>
I see
<a5i>
thanks waterlink
a5i has quit []
<waterlink>
btw, @jhass, putting ABTest logic to Commentable is really a bad idea, since usually ABTest logic needs to know about http request (if we are talking about web), or some sort of session. It would be mixing domain and presentation logic. And it would be really troublesome to get this session data there right to the Post model. Probably every usage of Post model would have to be altered..
<waterlink>
The other thing, if one will want to run ABTest only on Post and News, but not on Chapter for example (just making up some related domain models), but all of them include Commentable, here you got another problem..
DerisiveLogic has joined #crystal-lang
<BlaXpirit_>
Syntax error in ./libs/csfml/graphics_obj.cr:5687: expecting identifier 'end', not 'EOF'
<BlaXpirit_>
fun
<jhass>
not properly indented? :P
DerisiveLogic has quit [Ping timeout: 244 seconds]
a5i has joined #crystal-lang
DerisiveLogic has joined #crystal-lang
DerisiveLogic has quit [Remote host closed the connection]
<BlaXpirit_>
i want it to detect missing "end"s based on indentation
<jhass>
use python
<BlaXpirit_>
and definitely not just point to the end of the file whenever there is a mismatch
<BlaXpirit_>
jhass, i do use it
<BlaXpirit_>
i'm not even saying crystal should be indentation-based
<BlaXpirit_>
(that would be the best, but whatever)
JBat has quit [Quit: Computer has gone to sleep.]
wanderer_ has joined #crystal-lang
wanderer_ has quit [Client Quit]
<BlaXpirit_>
just realized my text editor can do it. for ruby, at least