by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Apr 08 16:03
    davidgiven opened #312
  • Feb 26 08:49
    desca595 removed as member
  • Jan 15 09:58
    CrazyFlasher synchronize #80
  • Jan 15 09:23
    CrazyFlasher commented #311
  • Jan 15 09:17
    CrazyFlasher opened #80
  • Jan 15 08:43
    CrazyFlasher commented #311
  • Jan 15 08:43
    CrazyFlasher commented #311
  • Jan 15 08:26
    CrazyFlasher commented #311
  • Jan 14 08:30
    CrazyFlasher edited #311
  • Jan 14 08:30
    CrazyFlasher opened #311
  • Oct 23 2019 16:33
    CrazyFlasher commented #310
  • Oct 23 2019 16:31
    CrazyFlasher commented #310
  • Oct 23 2019 16:30
    CrazyFlasher commented #310
  • Oct 23 2019 16:30
    CrazyFlasher commented #310
  • Oct 23 2019 13:15
    st3veV commented #310
  • Oct 23 2019 13:00
    CrazyFlasher opened #310
  • Oct 21 2019 20:08
    CrazyFlasher edited #309
  • Oct 21 2019 20:07
    CrazyFlasher opened #309
  • Oct 21 2019 10:42
    back2dos reopened #308
  • Oct 21 2019 10:42
    back2dos commented #308
MIchael Solomon
@mikicho
I'm feeling like a man in a desert that just get a bottle of water 0_0
Until I grasp the triggers, this is also valid? (in module)
how I want that one view will lead to google login and one to facebook, but they override each other
this._map(ILoginService, services.google.Login);
this._map(ILoginService, services.facebook.Login);
St3veV
@st3veV
yeah, as you said, these are going to override each other because mappings are only 1:1... for those cases there are "named mappings" - it's the last parameter which is optional... so you can do:
this._map(ILoginService, services.google.Login, "google");
this._map(ILoginService, services.facebook.Login, "facebook");
MIchael Solomon
@mikicho
Yeah, I saw that, but than I got weird error at runtime
uncaught exception: Error: hex.module.dependency.RuntimeDependencyException at hex.module.dependency.RuntimeDependencyChecker#check line:30 in file 'RuntimeDependencyChecker.hx' | '{
type : {
name : [modules,login,services,ILoginService]
}
}' dependency is not available during 'modules.login.LoginModule' initialisation.
St3veV
@st3veV
yes, that's quite expected because you have to define your dependency with the name as well
MIchael Solomon
@mikicho

what I'm missing?

var rd = new RuntimeDependencies();
rd.addMappedDependencies([{type: ILoginService}]);

I saw that is hex.di.mapping.Mapping object and tried to add names too but get other weird error :O

rd.addMappedDependencies([
    {type: ILoginService, name:"google"},
    {type: ILoginService, name:"facebook"}
]);
uncaught exception: Error: hex.di.error.MissingMappingException at hex.di.reflect.InjectionUtil#applyPropertyInjection line:60 in file 'InjectionUtil.hx' | 'hex.di.Injector' is missing a mapping to inject into property named 'loginService' with type 'modules.login.services.ILoginService' inside instance of 'modules.login.controllers.LoginCommand'. Target dependency: 'modules.login.services.ILoginService|'
St3veV
@st3veV
basically once you define a mapping with a name you'll always have to specify it because otherwise the injector doesn't know what exactly you need... in the end injector is just a glorified map which contains names of mappings and instances (well it's a bit more complicated than that but in a nutshell that's what it is)... the name of the mapping is my.pack.Foo|[name] where name is whatever name you specify (if you don't specify nothing it defaults to empty string)... so for the injector there is a big difference when you ask for ILoginService| and ILoginService|facebook
so in your command you have to inject it with the name as well:
@Inject("facebook")
public var loginService:ILoginService;
St3veV
@st3veV
OR because the injector is dealing with runtime instances, you can actually remap things during runtime so you can have a command that takes a facebook service and maps it to the generic/noname/emptystring (not sure how to call that but I hope you get the idea) name and your command can then inject it without caring what service it's communicating with and when youre done with macro execution you can then unmap your service from the generic name
MIchael Solomon
@mikicho

Hmm.. interesting! but than it means I have different vars for each login method in my command...
I tried to "cheat" on it with typedef:

typedef IGoogleLoginService = ILoginService;
typedef IFacebookLoginService = ILoginService;

and then:

this._map(IGoogleLoginService, services.google.Login); 
this._map(IFacebookLoginService, services.facebook.Login);

But with no success

oh... didn't see your second msg...
MIchael Solomon
@mikicho
I think I understand! also your help put lot of light on the "mapping" thing.
gonna try it :)
Thank you soooo much!
St3veV
@st3veV
well of course ideally you have just one variable and only one login service... basically the best way would be to have two login modules... because that's what you're trying to do... I assume the implementation differs only in the service and a view... so you can have a general purpose login module with all the wiring which depends on two things - ILoginSevice and ILoginView... everything within the module doesn't know what it's dealing with and you construct those two things outside of the module and pass them in (for example in the constructor of the module)... when you'll have two modules living side by side and dealing with login and one of them will fire event/trigger that user has logged in... this way you can easily scale the whole thing horizontally just by adding views and services and the whole login problematic would be encapsulated inside one isolated general purpose module
no problem at all :)
St3veV
@st3veV
injector really isn't that complicated thing but for some reason many people think about it as some kind of magic... really, think about it as a map of names and instances... but generally I'd discourage remapping things at runtime because you can very easily shoot yourself in the leg if you're not carefully keeping track on what's mapped to what... that's why I'd suggest the second thing I wrote... single responsibility module which communicates only through interfaces and the dependencies are not instantiated within the module but outside of it
MIchael Solomon
@mikicho
Read twice to fully understand and I see what you mean...
Just to be sure you recommend one module that contains the command, viewHelper and the model and one module (or more) that contains the service and view?
Sounds better, but where I should "pass them in"?
Anyway I going try to do that...
St3veV
@st3veV
well you construct your module somewhere, don't you? I guess you're not using DSL configuration yet so somewhere you're doing new LoginModule()... and at that place you construct your view and service and do new LoginModule(facebookView, facebookService); and the same thing with google... so you'll end up with two instances of login module which work independently on each other... and eventually one of them will dispatch/trigger and event which will say that user is logged in and at that point you have what you need (the logged in user details) and you can safely destroy both of the modules as you don't need them anymore... the main point is that your login module will never know what login method it's actually using (and it doesn't really care)... so later if you then want to add for example twitter login, you just implement your twitter service and view, make another instance of your module and you're all set up... you can have this whole thing encapsulated in another module or it can be just part of your configuration - eventually you have to somewhere specify what login methods are going to be used
MIchael Solomon
@mikicho
Thank you! I think I understand, I'm trying now to implement this :) (and switch/give a chance to triggers too)
Laurent Deketelaere
@aliokan
You have an example of trigger usage in https://github.com/doclerlabs/hexTodoMVC
MIchael Solomon
@mikicho
Thanks! so this project before, didn't notice it using triggers
MIchael Solomon
@mikicho
Hey,
I moved to Triggers and after you get the point it's really more continence than events...
Now I'm not sure how I should to forward the click event from the view(UI) to my service, previously I used command but in the todoMVC example I see using in simple controller...
what the different between command and controller? when I should using command?
MIchael Solomon
@mikicho
@st3veV What I don't understand in your method (of two modules, one "controller" module and one module for the services and views) is why I need modules for services and views(without model)? they live outside the modules isn't? (inside the modules you have only the Interfaces)
and I'm using DSL because all the guides/examples are with it. maybe this is the reason I have some difficult to see the whole picture...
MIchael Solomon
@mikicho

Also, I can (and it will be "right") to do something like:
< login module>

<argument>googleLoginService</argument>

<argument>googleLoginView</argument>
</login module>

< login module>

<argument>facebookLoginService</argument>

<argument>facebookLoginView</argument>
</login module>

X twitter, github, etc...

St3veV
@st3veV
I didn't meant it as needing a additional module for services and views... if you now imagine the dsl you wrote inside its own context - that's the "third module"... the whole handling of login with all it's methods closed inside one big module... where the big module will be the context itself (the context also implements IContextModuleso you can use that just as another module)... so in your application DSL you will only include the "big" module, add listeners to it and on the big scope you don't even have to worry about login methods
St3veV
@st3veV

now that you already work with DSL, there are two types of DSL - XML and "flow"... beside the flow DSL having much more compact syntax it also provides few features that are not available in the XML and one of them is "import"... in flow you can do internalModule = new Context("path/to/internal/flowDSL.flow"); and this will instantiate and execute your configuration so you can literally use the context as other module.

Of course our documentation is not really covering everything but we have pretty good test suite which can be use as examples of supported features, you can find those here: https://github.com/DoclerLabs/hexDSL/tree/master/test/context and https://github.com/DoclerLabs/hexIoC/tree/master/test/context

I hope I'm not confusing you too much introducing those new not very well documented things but I hope you'll find them better in a same way like the Events vs. Triggers topic... the flow DSL is really superior to the XML one in many ways.
MIchael Solomon
@mikicho
image.png
After all the info you got me I started to trying to play with hexMachina test, super fun till now.
just a question, I know that reflection can have very bad performance, why are you guys using it in the MacroAdapterStrategy? there is a tricky macro trick here ?:)
MIchael Solomon
@mikicho
Also, I'm playing now with testEventTrigger test, and see that the receiver get the message between 300-350 ms, it's huge amount off time for dispatching a message isn't?, it's lot of time only because it's test?
image.png
St3veV
@st3veV
So... just to explain why some things are using reflection when the reflection is bad for performance... hexMachina is a project with history and is develop mainly to serve the needs of one particular big closed source project... and that project has a history as well... mainly the history is that it was in flash :) and when last year all the major browsers announced that flash will be turned off by default there was a need to quickly rewrite everything to html+js and quickly convert as3 devs to haxe... reflection all over the place made the framework more similar to Robotlegs which was used in the flash version and increased speed of porting the code and developers adoption... All the events, macro strategies, adapter strategies, runtime xml compiler etc are in the framework for exactly that reason - legacy. Currently as the "main" project evolves the team is starting to refactor everything and get rid of all those reflection based and type unsafe features and switch to static compiler and Triggers (don't confuse it with eventTrigger, because that thing is still using events), Expects to produce more compact, faster and type-safe code... And that's why I keep recommending you all the nicer features even though they're not really documented. ;)
and to your second question... 300ms seems a way too much... also the way you're measuring is a bit unusual... personally I'd create a Timer.stamp(), save it before the call as start time and when the call arrives trace("time " + (Timer.stamp()-startTime));... that should give you a a more accurate picture of how long things take
MIchael Solomon
@mikicho
Hey, I decided to start from the beginning and not use DSL because it's just "write the code for me" and hiding things and makes it more difficult to understand.
In hello world example, why the controller implements ICommandTrigger? https://github.com/DoclerLabs/hexMachina-HelloWorld/blob/master/src/module/control/HelloWorldController.hx
MIchael Solomon
@mikicho

As I said, I'm not using DSL right now, I'm trying to create a simple hello world base on the Hello World example, it looks everything works fine except that I get runtime error the my injected "model is undefined", I think it because my module and my view need to be under a context this is my current code:
Main.hx

class Main {
    static function main() {
        var view = new HelloWorldView();
        var module = new HelloWorldModule(view);
        module.initialize();
    }
}

HelloWorldController.hx

class HelloWorldController implements ICommandTrigger implements IHelloWorldController {
    @inject
    var model:IHelloWorldModel;

    public function sayHello(who:String) {
        // This line makes a runtime error "this.model is undefined"
        model.setMessage("Hello $who");
    }
}

How can I insert the view and the module into a context?

St3veV
@st3veV
Hello... sorry for the delay, I was on vacation and looks like @aliokan doesn't communicate much ;) ... so to answer first question - ICommandTrigger interface is there to provide the possibility to inject things in function bodies (yes, the name is a bit misleading)
St3veV
@st3veV
and for the second question... I think the problem is that the Inject metadata should be with uppercase "I" otherwise it's not processed by the reflection builder. If you're using the exactly same module as it's in the hello world repository to model and controller are properly mapped so there shouldn't be any issue with the way you're initializing things
MIchael Solomon
@mikicho
Thanks, I'm hope that you did well in yours vacation!
This was the problem :\
I struggled with that till you answered to me and I thought that it isn't working because the module and the view should be in some context like in the .flow files. why in flow files they start with: @context( name = 'applicationContext' ) {why this line is necessary?
module have it's own context? injector?
St3veV
@st3veV
the @context is to provide scope for the "application" (where application is a very vague term) - this block basically represents the same thing as a root node in XML DSL and it creates ApplicationContext but it can be used just the same as a module (both module and application context implement the same interface IContextOwner which exposes injector)... so to answer the second question - both module and context have injector, both have things mapped into the injector but they serve slightly different purpose... even though sometimes they can be used interchangeably (and there is a plan to allow that for more cases)
in theory the HelloWorld example could be created completely without the module class because that one only maps things into its internal injector and connects listeners... the only thing that's currently not possible to do without the module class is to deal with the events (the override function _onInitialisation() part) but that could be achieved by simply calling the controller directly from the Main class
MIchael Solomon
@mikicho
so module in @context is like context in context?
"HelloWorld example could be created completely without the module class " do you mean that ApplicationContext can use instead?
Thanks I'm continue to dig in hexMachina :)
MIchael Solomon
@mikicho
BTW: I encounter an interesting issue, when I'm trying to open popup in service that triggered by user click the browser(FireFox) block to popup, probably because there is some code after the click and the browser don't understand that the user is clicked for the popup. did you encounter that?
MIchael Solomon
@mikicho

Like this post

The general rule is that popup blockers will engage if window.open or similar is invoked from javascript that is not invoked by direct user action. That is, you can call window.open in response to a button click > without getting hit by the popup blocker, but if you put the same code in a timer event it will be blocked. Depth of call chain is also a factor - some older browsers only look at the immediate caller, newer
browsers can backtrack a little to see if the caller's caller was a mouse click etc. Keep it as shallow as you can to avoid the popup blockers.

St3veV
@st3veV
in sense module inside a context is a context inside a context, yes... essentially both things are doing the same thing - providing scope, they both have injector and they both maintain set of instances that are wired together... in the end this is a matter of taste and it also depends on the way you want to use the DSL... for example you could do:
    • Single application context that contains modules which contain functionality
      or
    • Single application context which contains other contexts which contain functionality because many times all you need is to expose some controllers API and wire it to another controller which you can do in the main context... basically you can decide to treat the flow file as a module definition
about the popup problem... I know that this is happening in browsers for years now but afaik I never encountered it but that's given by the nature of the projects I work on... the hexMachinas main user is single page app (although complicated and large) and my hobby project is a game so there was never need to open another window
St3veV
@st3veV
but to provide some advice - you don't have to inject only instances, you can also inject methods and call them directly to reduce the stack... for example you can do this:
@Inject
public var openWindow:Void->Void;

// ....

function onClick(e) {
    openWindow();
}
MIchael Solomon
@mikicho
Thanks, all the context in context is actually little weird but I think I'll dig in it later.
About the popup solution, first of all cool! second, the popup is google login and opened by service, if I'll call the service directly by the view it's not "kill" the module concept? I mean, suddenly I just skipping from the view to the service. little weird isn't?
I just upload my code to github if you may check it out and correct me if I'm doing things wrong, I'm not using DSL for now :) sorry if I'm bother you :O
MIchael Solomon
@mikicho
it's incomplete, but the only missing part is the "communication" between servie to model after the service is done, (i.e the complete service event), i'm wondering if I should to replace it with sync service instead of async one