Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

maria.subclass without namespace #68

Open
viking opened this issue Aug 9, 2013 · 5 comments
Open

maria.subclass without namespace #68

viking opened this issue Aug 9, 2013 · 5 comments

Comments

@viking
Copy link

viking commented Aug 9, 2013

I'm attempting to switch my application to an AMD style. Currently, maria.subclass and friends receive a namespace argument that is expected to contain all of the relevant classes for the application. However, using AMD, all of my classes will be provided via arguments in my define function.

Is there an alternative to creating my own namespace object and assigning all of the classes into it so that it can be passed into maria.subclass short of recreating all of the functionality that maria.subclass (and maria.ElementView.subclass, etc) provides?

@viking
Copy link
Author

viking commented Aug 9, 2013

For example, I could do this:

define([
  'lib/maria',
  'models/FooModel',
  'controllers/FooController'
], function(maria, FooModel, FooController) {
  var namespace = {
    FooModel: FooModel,
    FooController: FooController
  };

  maria.ElementView.subclass(namespace, 'FooView', {
    uiActions: {
      'click .foo': 'onFooClick',
      'click .bar': 'onBarClick'
    },
    properties: {
      /* more stuff here */
    }
  });

  return namespace.FooView;
});

But creating the namespace object seems like a step that could be avoided somehow. Maybe by making the namespace parameter optional in maria.subclass.

Another option would be defining the entire application in a single file, but I want to avoid doing that.

Any ideas?

Thanks in advance.

@viking
Copy link
Author

viking commented Aug 9, 2013

I suppose I could assign only the classes that maria.subclass needs into the namespace object.

@petermichaux
Copy link
Owner

A bit of philosophy about the various subclass functions in Maria: These subclass functions are purely a sugar layer that sits on top of the actually core of Maria. That core is the constructor functions for maria.Model, maria.View, etc. The core is what defines the important MVC relationships that coordinate a running application built with Maria. The sugar layer is intended to reduce what you have to type when coding your application. The sugar is designed for a variety of writing styles but won't suit everyone's preferences or everything that needs doing. If and when the sugar layer is too limited or does not fit what you are trying to do, the solutions are to modify/extend the sugar layer or abandon it altogether and write a new sugar layer that you like.

It is the sugar layer, and only the sugar layer, that uses the namespace object to which you refer. The namespace object is critical in how the sugar layer works. The namespace object is how the "convention over configuration" binds all the classes together. For example, myApp.MyView will automatically use myApp.MyController based on naming convention. Maria looks in the myApp object to find the controller constructor. I suppose that the namespace object could be set to window if an application developer didn't really want to use a namespace object. If the namespace parameter was made optional to the various subclass functions, then a default value of window would seem appropriate.

I understand that you find creating the namespace object in your example is unappealing. I agree. That is boilerplate that no one would want to type for every class definition. (AMD style does introduce boilerplate.)

I understand you do not want to write your entire application in a single file. Fifty-thousand line files are not friendly.

Maria needs to be either told which controller constructor is used for a particular view, for example, or needs to know where to find it. The sugar allows both options. The less you type, the more it will find for you.

Your example code doesn't quite show what, I expected. You've included a model but I expected to see a template. Here is a possibility where there is no dependence on convention. Everything is configured.

define([
  'lib/maria',
  'templates/FooTemplate',
  'controllers/FooController'
], function(maria, FooTemplate, FooController) {
  var obj = {};
  maria.ElementView.subclass(obj, 'FooView', {
    uiActions: {
      'click .foo': 'onFooClick',
      'click .bar': 'onBarClick'
    },
    template: FooTemplate,
    controllerConstructor: FooController
    properties: {
      /* more stuff here */
    }
  });

  return obj.FooView;
});

This could be shortened if subclass returns the created constructor function (which it does not currently do but I've considered)

define([
  'lib/maria',
  'templates/FooTemplate',
  'controllers/FooController'
], function(maria, FooTemplate, FooController) {

  return maria.ElementView.subclass(null, 'FooView', {
    uiActions: {
      'click .foo': 'onFooClick',
      'click .bar': 'onBarClick'
    },
    template: FooTemplate,
    controllerConstructor: FooController
    properties: {
      /* more stuff here */
    }
  });
});

For use with AMD, I'm not sure how we could make the Maria sugar layer require less configuration and use more convention as AMD is actually intentionally designed to have the developer be explicit about everything.

@viking
Copy link
Author

viking commented Aug 9, 2013

Thanks, that information helps a lot. (My example erroneously had a model instead of a template in the define function.)

I think I will continue to use the subclass function and explicitly set the template and controllerConstructor properties as you suggest instead of building my own sugar layer. Or I could just write a simple wrapper around the sugar layer to return the new constructor.

Ex:

function subclass(klass, name, options) {
  var namespace = {};
  klass.subclass(namespace, name, options);
  return namespace[name];
}

Thanks again for the advice.

@petermichaux
Copy link
Owner

That looks like a good solution to get moving immediately.

If you are not using any of the name-based conventions, then I think you could do the following.

function subclass(klass, options) {
  var namespace = {};
  klass.subclass(namespace, 'a', options);
  return namespace.a;
}

I am considering (partly thanks to this issue) making this part of Maria so you can optionally write

myApp.MyView = maria.ElementView.subclass({});

This is how I originally had Maria designed but when I wanted to use name-based conventions it broke down and so I switched to the three arguments of the subclass method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants