Skip to content

v0.8 #87

@creynders

Description

@creynders

So I started on the next minor/major version. I'd been thinking about 0.7.2 and what needed to be done: updating the tests, documentation and a number of patches here and there to get things better, until I suddenly realised I should be focusing on getting the next major version out instead of trying to modify 0.7 towards what I'd really want.

So, here's what's happening: I'm trying to

  • drop the hard dependency on backbone. ATM it looks like if Backbone's present then a number of sugary things and functionality will be added, but if it's not things will still work as they should, except maybe you'll have to do one or two things manually.
  • make it event framework agnostic. This one's rather tough and obviously not entirely possible. However I have a few ideas on how to approach this.
  • shy away from MVC concepts in the API. This means: no longer wireView or wireCommand. Of course it will still be possible to wire views, commands et cetera. But just as we have no wireModel I think it's beneficial to make Geppetto a more flexible library which can be used in a MVC, MVVM, MyOwnCustomWhateverConcept w/o having the feeling of trying to fit a square peg in a round hole. As implied in Bringing Geppetto to life. #86 this could be potentially a powerful approach and selling point. To achieve this it's necessary to make the Geppetto concepts dedicated and not adhere to another paradigm. Obviously the role of the documentation will be to show the way on how to use it in an MVC or similar context.
  • move towards a fluent API. Yeah, it's hipster, but it's hip for a reason. If done well it seriously increases readability. I've done many sketches, some of which found their way into Fluent interface #73 but most didn't survive the drawing board. After a LOT of weighing, meditating, magic-8-balling and head banging I've decided to go for the fully descriptive, symmetrical fluent interface, which will turn out to be something like this:
loginContext.wire(15)
    .as.value("timeout duration");

loginContext.wire(ServiceRequest)
    .as.producer("serviceRequest");

loginContext.wire(AuthService)
    .as.singleton("authService")
    .using.wiring({
        timeout : "timeout duration",
        base : "serviceRequest"
    });

loginContext.wire(LoginCommand)
    .to.event("loginview:authentication:requested")
    .using.wiring("authService");

mainContext.wire(LoginView)
    .as.factory("loginPanel")
    .using.parameters({
            model : new AuthModel()
        })
        .and.handlers({
            "authservice:authentication:completed": "close",
            "authservice:authentication:failed": function(){
                this.show("ERROR!");
            }
        })
        .and.context(loginContext);

mainContext.wire(MainView)
    .using.wiring({
        loginRegion: "loginView"
    });
mainContext.trigger("maincontext:startup:requested");

Forgive me the convoluted example, but I tried to cover as much ground as possible. I think most of it is pretty self-explanatory if you're familiar with the current version. Obviously everything that's done using the context API here, can be configured inside your components as well: wiring, handlers, et cetera.
As you can see views are no longer wired as "view", but as factory. And wireClass is replaced with as.producer which is a better fitting term, IMO.
There's a new concept as well, "providers":

function QueueProvider(){
    this.queue = [];
};

QueueProvider.prototype.provide = function(ItemClass){
    var item = new ItemClass()
    this.queue.push(item);
    return item;
}

var requesterQueue = new QueueProvider();

context.provide("queue")
    .using(requesterQueue.provide);

context.wire(Requester)
    .as.queue("requester");

context.wire(SomeService)
    .using.wiring({
        requester: "requester"
    });

Now, what's this all about? ATM Geppetto contexts allow for registering objects as singletons, values, ... but I wanted to allow developers to create their own types. E.g. the above example would allow maintaining a list of all Requester instances. The provide method receives an ItemClass, which in this case is Requester. It creates a new instance and stores it in a queue.
The SomeService class is totally oblivious to whether it's receiving a singleton instance, or a new instance, or (in this case) a new instance which is stored in a queue.
As you can see the Context#provide method accepts a string which is used to expand the context API. I passed 'queue' to it, which adds a queue member to wire.as.
This allows for extremely powerful and versatile concepts and patterns. E.g. I can imagine use cases for an "object pool" or "cyclic" provider for instance.

  • better lifecycle management and less intrusive constructor handling ATM the wired constructors are wrapped, but I'm going to change that, since some people had a really hard time accepting that cough @mmikeyy cough. We'll resolve dependencies through a (wrapped) initialize method which allows for a better life cycle as well: constructor: pre-resolution, initialize: post-resolution.

Well, that's about it FTM. As always, @geekdave please pull the reigns if I'm off into cuckoo-land.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions