using export in alloy controller versus attaching functions directly to the '$' scope - titanium-alloy

here is the code of an alloy controller written in two different ways. Although the both work the same, Which one might be best practice?
example 1 of controller.js:
var currentState = true;
$.getState = function(){
return currentState;
}
example 2 of controller.js:
var currentState = true;
exports.getState = function(){
return currentState;
}

Titanium is based on the CommonJS framework. The exports variable is a special variable used typically to expose a public API in a class object. So when you want to expose a method of doSomething() on the MyModule.js class you would use the exports variable like this:
exports.doSomething() = function(args) {
//Some really cool method here
};
Then reference that class using
var myModule = require('MyModule');
myModule.doSomething();
However when referencing a view object the typical way to reference the is using the $. shortcut. You can see they prefer that method in the official documentation.
http://docs.appcelerator.com/platform/latest/#!/guide/Alloy_XML_Markup

The $ variable holds a reference to your controller instance. It also contains some references to all indexed views (understand, views for which you supplied an index in you xml markup).
Both ways are strictly equivalent as, during the compilation, Alloy will merge the content of the exports with your controller referenced in $. Adding them directly to the instance won't change a thing.
Neverthless, developers are used to see the public API as the set of functions exported via the special variable exports; Thus, I will recommend to keep using it in a clean and clear way (for instance, defining your functions in your module scope, and only expose them at the end or beginning of your controller).
function myFunction1 () { }
function myFunction2 () { }
function myFunction3 () { }
exports.myFunction1 = myFunction1;
exports.myFunction3 = myFunction3;
Thereby, your API is quite clear for people diving into your source code. (A readMe file is also highly recommended :) ).

Related

Typescript reflection - required parameters & default values

In short: is there a way to know if a typescript parameter is required and/or has a default value?
Longer version:
Say I have the following file:
//Foo.ts
class Bar {
foo(required:string,defaultValue:number=0,optional?:boolean) {
...
}
}
I would like to know of each of the parameters:
the name
the type
is it required?
does it have a default value?
I have succesfully used method decorators with the TypeScript reflection API to get the types of the parameters, I've used this method to get their names, but so far I have not found a way to know if a variable is required and/or has a default value.
I know the typescript compiler itself can be used from within typescript. So I'm wondering if there is a way to use the parse tree of the compiler to see if a parameter is required and/or has a default value?
How would that work?
If you want to do this from scratch...
On a high level, one way of doing it is to:
Figure out how to get the SourceFile node using the compiler api of your file. That requires a bit of an explanation in itself.
From there, use the api's forEachChild function to loop over all the nodes in the file and find the node with a kind of SyntaxKind.ClassDeclaration and .name property with text Bar.
Then loop over all the children of the class by again using the api's forEachChild function and get the ones that has the kind SyntaxKind.MethodDeclaration and .name property with text foo.
To get the parameters, you will need to loop over the method node's parameters property.
Then for each parameter node, to get the name you can call .getText() on the .name property.
You can tell if the parameter is optional by doing:
const parameterDeclaration = parameterNode as ts.ParameterDeclaration;
const isOptional = parameterDeclaration.questionToken != null || parameterDeclaration.initializer != null || parameterDeclaration.dotDotDotToken != null;
Or you could use the TypeChecker's isOptionalParameter method.
To get its default expression, you will just have to check the initializer property:
propertyDeclaration.initializer;
To get the type use the TypeChecker's getTypeOfSymbolAtLocation method and pass in the symbol of the node... that gets a little bit complicated so I won't bother explaining it (think about how it's different with union types and such).
Don't do it from scratch...
I've created a wrapper around the TypeScript compiler api. Just use this code with ts-simple-ast (edit: Previously this talked about my old ts-type-info library, but ts-simple-ast is much better):
import { Project } from "ts-morph";
// read more about setup here:
// https://ts-morph.com/setup/adding-source-files
const project = new Project({ tsConfigFilePath: "tsconfig.json" });
const sourceFile = project.getSourceFileOrThrow("src/Foo.ts");
const method = sourceFile.getClassOrThrow("Bar").getInstanceMethodOrThrow("foo");
Once you have the method, it's very straightforward to get all the information you need from its parameters:
console.log(method.getName()); // foo
for (const param of method.getParameters()) {
console.log(param.getName());
console.log(param.getType().getText());
console.log(param.isOptional());
console.log(param.getInitializer() != null);
}

Meteor helper methods

I want to write some helper functions that I can use in my other JavaScript files.
It says here:
Some JavaScript libraries only work when placed in the client/compatibility subdirectory. Files in this directory are executed without being wrapped in a new variable scope.
It seems a bit bizarre to me that I should have to throw all my libraries in a folder called compatibility. Generally "compatible" stuff is for legacy code that hasn't been upgraded to the new style. Is there no way to export modules so that I can access them in my other files?
Using this pattern now:
Util = (function(exports) {
exports.getFileExtension = function(filename) {
var i = filename.lastIndexOf('.');
return (i < 0) ? '' : filename.substr(i);
};
// more functions
return exports;
})(typeof Util !== 'undefined' ? Util : {});
Not sure if that's the best or not...but it appears to work.
It would be bizarre, you are right. Write your own code, just put it somewhere and it works. This refers to complicated frameworks that make a lot of functions all over the place, where no one has 'tamed' them to only expose a root object that all its powers spring from.
Please read "Namespacing and Modules" at
http://www.meteor.com/blog/2013/08/14/meteor-065-namespacing-modularity-new-build-system-source-maps
It's helping you with built in maintainability for avoiding collisions with other things you write, which is largely what namespaces is for.
A good practice is to have your own helper object, named helper or util, where you put grouped things:
utils = {
distance_between: function(lat1,lng1,lat2,lng2) {
var radiusEarth = 3963.1676; // miles radius earth
var dLat = deg2rad(lat2-lat1); // deg2rad below
...
displayHumanReadableTime: function(timestamp){
var a = new Date(timestamp);
If the intention is to write Utility method then it can be written using the ECMA6 Script standard.
Write your method by exporting once in method.js and use it by importing in the desired file(s)
Ex:
export const MyUtilityMethod = function (){...} in /method.js
import {MyUtilityMethod} from './method.js'
Hope this helps.

Using asMock, how can I satisfy a concrete and interface requirement in SetupResult.forCall

The ValidationManager has a public Dictionary for storing UI components that implement the IValidatable interface.
I am testing a command class that needs an instance of ValidationManager and I want it to fail the validations. So I override the ValidationManager's "validateItem()" method like so:
var validationManagerRepos:ValidationManager = ValidationManager(mockRepository.createStub(ValidationManager));
var validationItem:IValidatable = IValidatable(mockRepository.createStub(IValidatable));
var validatableItems:Dictionary = new Dictionary();
validatableItems[validationItem] = false;
SetupResult.forCall(validationManagerRepos.validateItem(validationItem)).returnValue(false);
My problem is in the execute method of the command. It checks to see if the validationItem is both a DisplayObject (isVisble) and IValidatable. Any slick way to stub a typed object AND an interface? Or do I just need to create an instance of some existing object that already satisfies both?
for (var iVal:Object in validationManager.validatableItems)
{
if (isVisible(DisplayObject(iVal)))
{
passed = validationManager.validateItem(IValidatable(iVal));
eventDispatcher.dispatchEvent(new ValidationEvent(ValidationEvent.VALIDATE_COMPLETED, IValidatable(iVal), passed));
if (!passed)
{
allPassed = false;
}
}
}
I'm fairly sure you can't do both within asMock. It's a limitation of the Flash Player because of lack of polymorphism.
I believe what you'll have to do is create a testing object that does both (extend DisplayObject and implement IValidatable) and create a mock object of that.
The concept of a "multimock" is certainly possible, but floxy (the framework that asmock uses to generate dynamic proxies) doesn't support it. I previously considered adding support for it, but it would be difficult to expose via the various Mock metadata and there's be other issues to worry about (like method name clashes).
I agree with J_A_X's recommendation of creating a custom class and then mocking that.

Flex: How to use flashvars from different classes

I am just learning actionscript, so come across the problem
In my application I often call to different web services, and because I don't want to hardcode urls to them in my code, I am passing urls to the services as flashvars.
Currently I am doing it this way:
public var siteUrl:String;
public var gameId:String;
public function main():void
{
siteUrl = Application.application.parameters.siteurl;
gameId = Application.application.parameters.gameid;
Where main is a function, which is called on application's creation complete event.
This way I can call both variables from main file of the application but I want to access them from other files. (other as classes)
So is there a way to create class with constants and init values there with flashvars so I can use them everywhere (after importing of course)
The parameters are just stored in that Application.application.parameters object, and that's static. There's no reason you couldn't access that from other classes in your code.
If you want to write a class that wraps the parameters (maybe validates them or something) you could do that fairly easily. You can use a for each loop to loop over all the parameters. Something like:
var params:Object = Application.application.parameters
for(var name:String in params) {
var value:String = params[name] as String;
/* do something with the param */
}
If you want your class to actually verify things then it could just check for each parameter it expects and store it in a local variable.
It really just depends on your own preferences. Some people are fine with accessing the parameters object when they need it. Some people like having the extra code-completion by having a config class that actually defines all the expected config variables.
Update in response to comment:
Instead of having one module declare the variable and have other modules have to depend on that one to access the property it would be cleaner to have a single config module that everything that needs it would all use.
You could use a static class or singleton or some IoC stuff. Just for simplicity I'll show you a way you can do it with a static class.
class MyConfig {
private static var _infoService:String;
private static var _someOtherParam:int;
public static function get infoService():String { return _infoService; }
public static function get someOtherParam():int { return _someOtherParam; }
public static function initParams():Void {
var params:Object = Application.application.parameters;
_infoService = params.infoservice;
// just assuming you have a method to convert here. don't remember the
// code off the top of my head
_someOtherParam = convertToInt(params.someOtherParam);
}
}
Make sure when your app initializes it calls MyConfig.initParams(). You can have that method actually validate that it gets everything it expects and throw exceptions (or return an error) if there's a failure if you want.
Then wherever you need to use that config within your code you just import your config class and access the param. So getting infoService would just be:
var infoService:String = MyConfig.infoService;
Personally I wouldn't use a static class, but it was the easiest to show.

What is the best way to reuse functions in Flex MVC environment?

I am using a Cairngorm MVC architecture for my current project.
I have several commands which use the same type of function that returns a value. I would like to have this function in one place, and reuse it, rather than duplicate the code in each command. What is the best way to do this?
Create a static class or static method in one of your Cairngorm classes.
class MyStatic
{
public static function myFunction(value:String):String
{
return "Returning " + value;
}
}
Then where you want to use your function:
import MyStatic;
var str:String = MyStatic.myFunction("test");
Another option is to create a top level function (a la "trace"). Check out this post I wrote here.
You have lots of options here -- publicly defined functions in your model or controller, such as:
var mySharedFunction:Function = function():void
{
trace("foo");
}
... static methods on new or existing classes, etc. Best practice probably depends on what the function needs to do, though. Can you elaborate?
Create an abstract base class for your commands and add your function in the protected scope. If you need to reuse it anywhere else, refactor it into a public static method on a utility class.

Resources