Categories
Haxe

A Haxe/JS Debugging Tip

When targetting Haxe JS in Haxe 3, the output is “modern” style, which means, to prevent polluting the global namespace or conflicting with other libraries, the output is wrapped in a simple function:

(function() {})()

Which is great.  And if you place breakpoints in your code, using:

js.Lib.debug();

Then your browser will launch the debugger inside this Haxe context, and you have access to all your classes etc.  But what if you want to fire up the browser’s JS console, and gain arbitrary access to something in your Haxe code?  Because it’s all hidden inside that function, you can’t.

Unless you have a workaround, which looks like this:

class Client 
{
    @:expose("haxedebug") @:keep
    public static function enterDebug()
    {
        js.Lib.debug();
    }
}

What’s going on: we have a class, and a function: “enterDebug”.  This function can go in any class that you use, really – it doesn’t have to be in Client or your Main class or anything.

The “js.Lib.debug()” statement launches the debugger in the haxe context, as described before.  But the “@:expose” metadata exposes this function outside of the Haxe context.  The string defines what we expose it as: rather than the default “Client.enterDebug()”, we’ll just have “haxedebug()”.  And the “@:keep” metadata makes sure this won’t get deleted by the compilers Dead Code Elimination, even though we may never explicitly call this function in our code.

Now that we’ve done that, recompile, and voilà!  You can type “haxedebug()” into the Javascript console and start fiddling around inside the Haxe context.  Enjoy.

 

Categories
Haxe

Creating Complex URL Routing Schemes With haxe.web.Dispatch

Complex Routing Schemes with haxe.web.Dispatch

I’ve looked at haxe.web.Dispatch before, and I thought it looked really simple – in both a good and a bad way. It was easy to set up and fast. But at first it looked like you couldn’t do complex URL schemes with it.

Well, I was wrong.

At the WWX conference I presented some of the work I’ve done on Ufront, a web application framework built on top of Haxe. And I mentioned that I wanted to write a new Routing system for Ufront. Now, Ufront until now has had a pretty powerful routing system, but it was incredibly obese – using dozens of classes, thousands of lines of code and a lot of runtime type checking, which is usually pretty slow.

Dispatch on the other hand uses macros for a lot of the type checking, so it’s much faster, and it also weighs in at less than 500 lines of code (including the macros!), so it’s much easier to comprehend and maintain. To wrap my head around the ufront framework took me most of the day, following the code down the rabbit hole, but I was able to understand the entire Dispatch class in probably less than an hour. So that is good!

But there is still the question, is it versatile enough to handle complex URL routing schemes? After spending more time with it, and with the documentation, I found that it is a lot more flexible than I originally thought, and should work for the vast majority of use cases.

Learning by example

Take a look at the documentation to get an idea of general usage. There’s some stuff in there that I won’t cover here, so it’s well worht a read. Once you’ve got that understood, I will show how your API / Routing class might be structured to get various URL schemes:

If we want a default homepage:

function doDefault() trace ( "Welcome!" ); 

If we want to do a single page /about/:

function doAbout() trace ( "About us" ); 

If you would like to have an alias route, so a different URL that does the same thing:

inline function doAboutus() doAbout();

If we want a page with an argument in the route /help/{topic}/:

function doHelp( topic:String ) { 
 trace ( 'Info about $topic' ); 
} 

It’s worth noting here that if topic is not supplied, an empty string is used. So you can check for this:

function doHelp( topic:String ) { 
 if ( topic == "" ) { 
 trace ( 'Please select a help topic' ); 
 } 
 else { 
 trace ( 'Info about $topic' ); 
 } 
} 

Now, most projects get big enough that you might want more than one API project, and more than one level of routes. Let’s say we’re working on the haxelib website (a task I might take on soon), there are several pages to do with Projects (or haxelibs), so we might put them altogether in ProjectController, and we might want the routing to be available in /projects/{something}/.

If we want a sub-controller we use it like so:

/*
 /projects/ => projectController.doDefault("")
 /projects/{name}/ => projectController.doDefault(name)
 /projects/popular/ => projectController.doPopular
 /projects/bytag/{tag}/ => projectController.doByTag(tag) 
*/ 
function doProjects( d:Dispatch ) { 
 d.dispatch( new ProjectController() ); 
} 

As you can see, that gives a fairly easy way to organise both your code and your URLs: all the code goes in ProjectController and we access it from /projects/. Simple.

With that example however, all the variable capturing is at the end. Sometimes your URL routing scheme would make more sense if you were to capture a variable in the middle. Perhaps you would like:

/users/{username}/ 
/users/{username}/contact/ 
/users/{username}/{project}/ 

Even this can still be done with Dispatch (I told you it was flexible):

function doUsers( d:Dispatch, username:String ) { 
 if ( username == "" ) { 
 println("List of users"); 
 } 
 else { 
 d.dispatch( new UserController(username) ); 
 } 
} 

And then in your username class:

class UserController { 
 var username:String; 
 public function new( username:String ) { 
 this.username = username; 
 } 
 function doDefault( project:String ) { 
 if ( project == "") { 
 println('$username\'s projects'); 
 } 
 else { 
 println('$username\'s $project project'); 
 } 
 } 
 function doContact() { 
 println('Contact $username'); 
 } 
} 

So the username is captured in doUsers(), and then is passed on to the UserController, where it is available for all the possible controller actions. Nice!

As you can see, this better represents the heirarchy of your site – both your URL and your code are well structured.

Sometimes, it’s nice to give users a top-level directory. Github does this:

http://github.com/jasononeil/

We can too. The trick is to put it in your doDefault action:

function doDefault( d:Dispatch, username:String ) {
  if ( username == "" ) { 
 println("Welcome"); 
 } 
 else { 
 d.dispatch( new UserController(username) ); 
 } 
} 

Now we can do things like:

/ => doDefault() 
/jason/ => UserController("jason").doDefault("") 
/jason/detox => UserController("jason").doDefault("detox") 
/jason/contact => UserController("jason").doContact() 
/projects/ => ProjectController.doDefault("") 
/about/ => doAbout() 

You can see here that Dispatch is clever enough to know what is a special route, like “about” or “projects/something”, and what is a username to be passed on to the UserController.

Finally, it might be the case that you want to keep your code in a separate controller, but you want to have it stay in the top level routing namespace.

To use a sub-controller add methods to your Routes class:

inline function doSignUp() (new AuthController()).doSignUp(); 
inline function doSignIn() (new AuthController()).doSignIn(); 
inline function doSignOut() (new AuthController()).doSignOut(); 

This will let the route be defined at the top level, so you can use /signup/ rather than /auth/signup/. But you can still keep your code clean and separate. Winning. The inline will also help minimise any performance penalty for doing things this way.

Comparison to Ufront/MVC style routing

Dispatch is great. It’s light weight so it’s really fast, and will be easier to extend or modify the code base, because it’s easier to understand. And it’s flexible enough to cover all the common use cases I could think of.

I’m sure if I twisted my logic far enough, I could come up with a situation that doesn’t fit, but for me this is a pretty good start.

There are three things the old Ufront routing could do that this can’t:

  1. Filtering based on whether the request is Post / Get etc. It was possible to do some other filtering also, such as checking authentication. I think all of this can be better achieved with macros rather than the runtime solution in the existing ufront routing framework.
  2. LocalizedRoutes, but I’m sure with some more macro love we could make even that work. Besides, I’m not sure that localized routes ever functioned properly in Ufront anyway ;)
  3. Being able to capture “controller” and “action” as variables, so that you can set up an automatic /{controller}/{action}/{...} routing system. While this does make for a deceptively simple setup, it is in fact quite complex behind the scenes, and not very type-safe. I think the “Haxe way” is to make sure the compiler knows what’s going on, so any potential errors are captured at compile time, not left for a user to discover.

Future

I’ll definitely begin using this for my projects, and if I can convince Franco, I will make it the default for new Ufront projects. The old framework can be left in there in case people still want it, and so that we don’t break legacy code.

I’d like to implement a few macros to make things easier too.

So

var doUsers:UserController; 

Would automatically become:

function doUsers( ?d:Dispatch, username:String ) { 
 d.dispatch( new UserController(username) ); 
} 

The arguments for “doUsers()” would match the arguments in the constructor of “UserController”. If “username” was blank, it would still be passed to UserController.default, which could test for a blank username and take the appropriate action.

I’d also like:

@:forward(doSignup, doSignin, doSignout) var doAuth:AuthController; 

To become:

function doAuth( ?d:Dispatch ) { 
 d.dispatch( new AuthController() ); 
} 
inline function doSignup() (new AuthController()).doSignup(); 
inline function doSignin() (new AuthController()).doSignin(); 
inline function doSignout() (new AuthController()).doSignout(); 

Finally, it would be nice to have the ability to do different actions depending on the method. So something like:

@:method(GET) function doLogin() trace ("Please log in");

@:method(POST) function doLogin( args:{ user:String, pass:String } ) { 
 if ( attemptLogin(user,pass) ) { 
 trace ( 'Hello $user' ); 
 } 
 else { 
 trace ( 'Wrong password' ); 
 } 
}
 
function doLogin() { 
 trace ( "Why are you using a weird HTTP method?" ); 
} 

This would compile to code:

function get_doLogin() { 
 trace ("Please log in") 
} 

function post_doLogin( args:{ user:String, pass:String } ) { 
 if ( attemptLogin(user,pass) ) { 
 trace ( 'Hello $user' ); 
 } 
 else { 
 trace ( 'Wrong password' ); 
 } 
} 

function doLogin() { 
 trace ( "Why are you using a weird HTTP method?" ) 
} 

Then, if you do a GET request, it first attempts “get_doLogin”. If that fails, it tries “doLogin”.

The aim then, would be to write code as simple as:

class Routes { 
 function doDefault() trace ("Welcome!"); 
 var users:UserController; 
 var projects:ProjectController; 
 @:forward(doSignup, doSignin, doSignout) var doAuth:AuthController; 
} 

So that you have a very simple, readable structure that shows how the routing flows through your apps.

When I get these macros done I will include them in ufront for sure.

Example Code

I have a project which works with all of these examples, in case you have trouble seeing how it fits together.

It is on this gist.

In it, I don’t use real HTTP paths, I just loop through a bunch of test paths to check that everything is working properly. Which it is… Hooray for Haxe!

Categories
Edtech Haxe

It’s free, but do you mind paying?

Here’s something I’d like to see more of: UberWriter is free (open source, GPL3), yet by default if you go to install it you’ll have to pay $5.  The old “free as in freedom of speech” rather than “free as in free beer”.

From the creator’s point of view, “Free as in speech” means several things:

  • The project is open to collaboration – if you have something to add, please do!
  • If you see a different future for this project than I do, you don’t have to ask my permission.  You can build on what I’ve started and do something new and different.  I may or may not want what to merge your changes back in.
  • If you’re not someone that’s likely to pay me money (you have a different native language, you live in an area I can’t sell to, you’re don’t have enough money…) then that’s okay, feel free to take what I’ve done anyway and see if you can build on it.
  • If you’re really poor (developing world, unfunded startup, student) then you can still use the software and pay it back (or pay it forward) later.  I’m just glad people are using (and enjoying) something I’ve made.
  • If you’re worried about security, you can know exactly what your software is doing by getting a developer to audit the code.  I promise I’m not working for your corrupt government.
  • If I ever close shop and discontinue the product, you can keep using it, without having to worry about where to get new copies.  Feel free to make new copies, or to hire a developer to maintain it, even to release your own version.  I promise not to get angry.

But from the creator’s point of view, “free as in beer” has several negative implications:

  • I don’t have a strong plan to make money off this, so it will remain a side-project or a hobby.  I might love it, but I’ll never give it the time, money and support it needs to be amazing.
  • I have to pay my bills.  So the work I do that pays bills will always be more important than the work I do for this project.

Commercial projects that succeed (especially software projects) often have a founder who is hugely passionate about it, and absolutely stoked that they get to work on their passion as their full time job.  For many open source developers, this isn’t a reality.

So what if you want to balance those two things:

  1. Create, invent, make art.  And give it away to the world in the most generous, considerate way possible.
  2. Make money so that I can continue to develop this, perfecting it and supporting it and giving it every opportunity to succeed.

Well, that’s what UberWriter is doing.  It has all the same freedoms as “free as in speech”.  And if you really don’t want to pay for it, you can find ways to get it for free, and that’s allowed too, it’s not illegal and it won’t make the creator cry.  But, if you want to get it the easiest way, and you want to support the developer, it’s $5.

I hope he does well, makes some money, maybe even is able to make it his main job – so that he is empowered to make some good software become really great software.  And I hope to see more people balance this act of being generous with earning a living… myself included.

Categories
Haxe

20 Questions I Asked Myself

Bernadette Jiwa is a marketing / branding / idea-spreading expert, (and a Perth local!), and when you subscribe to her “The Story of Telling” she sends you a PDF with 20 questions to ask yourself before launching your next product or idea.

At WWX 2013, this year’s Haxe conference, I’ll be presenting a talk on developing Web Apps, and using “ufront” to do that.  Ufront is a framework made by mostly by Franco Ponticelli, and initially modelled on the .NET MVC framework.  Ufront is pretty powerful, but it’s lacked documentation and hasn’t had a lot of users.  I’ve used it for my last project, added a bunch of helpers, and think it’s ready for some more attention.  A re-launch, if you will.

So I went through the 20 questions Bernadette gives in her PDF, and tried to apply it to ufront, Haxe and web-apps.

My answers to the “20 questions” for ufront (PDF)

It was pretty eye-opening, and really helped me zero in on why I think this approach is better than rails, django, node/express or other frameworks.  I came up with this tagline:

ufront: the client / server framework for Haxe that lets you write the next big (website/web-app/mobile-app/game/thing)

Categories
Haxe

The new Map syntax in Haxe 3

I was using the Haxe3 Release Candidate for well over a month before I realised that the new Map data structures could be created with a nice syntax.  The basic gist is this:

var map1 = [ 1=>"one", 2=>"two", 3=>"three" ];

Like Arrays, but you use the “=>” operator to define both the key and the value.  And Haxe’s type inference is as strong as ever.  Here’s what the compiler picks up:

var map1 = [ 1=>"one", 2=>"two", 3=>"three" ];
$type (map1); // Map<Int, String>

var map2 = [ "one"=>1, "two"=>2, "three"=>3 ];
$type (map2); // Map<String, Int>

var map3 = [
    Date.now() => "Today",
    Date.now().delta(24*60*60*1000) => "Tomorrow",
    Date.now().delta(-24*60*60*1000) => "Yesterday"
];
$type (map3); // Map<Date, String>

var map4 = [
    { name: "Tony Stark" } => "Iron Man",
    { name: "Peter Parker" } => "Spider Man"
];
$type (map4); // Map<{ name : String }, String>

var map5 = [
    [1,2] => ["one","two"],
    [3,4] => ["three","four"],
];
$type (map5); // Map<Array<Int>, Array<String>>

So it’s pretty clever.  If for some reason you need to type explicitly to StringMap, IntMap, or ObjectMap, you can:

var stringMap:StringMap<Int> = [
    "One" => 1,
    "Two" => 2
];
$type(stringMap); // haxe.ds.StringMap<Int>

var intMap:IntMap<String> = [
    1 => "One",
    2 => "Two"
];
$type(intMap); // haxe.ds.IntMap<String>

var objectMap:ObjectMap<{ name:String }, String> = [
    { name: "Tony Stark" } => "Iron Man",
    { name: "Peter Parker" } => "Spider Man"
];
$type(objectMap); // haxe.ds.ObjectMap<{ name : String }, String>

But if you try to do anything too funky with types, the compiler will complain.  Haxe likes to keep things strictly typed:

var funkyMap = [
    { name: "Tony Stark" } => "Iron Man",
    { value: "Age" } => 25
]; // Error: { value : String } has no field name ... 
   // you are a bad person, and your items are not comprehensible 
   // to Haxe's typing system

Finally, Haxe won’t let you do define duplicate keys using this syntax:

var mapWithDuplicates = [
    1 => "One",
    2 => "Two",
    1 => "uno"
]; // Error: Duplicate Key ... previously defined (somewhere)

If you’re using an object map, it’s only a duplicate if you’re dealing with the exact same object, not a similar one.  For example, this is allowed:

var similarObjectKeys:ObjectMap<Array<Int>, String> = [
    [0] => "First Array object",
    [0] => "Second Array object"
]; // Works, you now have 2 items in your map.

But if you use the exact same object, Haxe will pick it up:

var key = [0];
var sameObjectKey = [
    key => "First Array object",
    key => "Second Array object"
]; // Error: Duplicate Key ...

So there you have it.  A nice feature that I didn’t see mentioned anywhere else.  Thanks Haxe team!

….

Update:

It’s worth mentioning that once you have created your map, you can use array access (“[” and “]”) to read or modify entries in your map.

var map = [ 1=>"one", 2=>"two", 3=>"three" ];

// Reading a value
map[1];   "one"
var i = 2;
map[i];   "two"
map[++i]; "three"

// Setting a value
map[4] = "four";
map[1] = "uno";
map[i] = "THREE";
map;   // [ 1=>"uno", 2=>"two", 3=>"THREE", 4=>"four" ]
Categories
Haxe

Trying to understand dependency injection

Coming closer to the end of writing my first really complex app, I’m beginning to wish I’d taken the time at the start to properly learn and grasp some of the concepts that I see other programmers using.  My client-side code uses a basic MVC pattern, but a bunch of Flash Developers use something that to me comes across as much more complex – as seen in RobotLegs or some of the Haxe ports, such as MMVC.

These frameworks are all about Inversion Of Control (and because we love acronyms: IOC).  And they use Dependency Injection (DI) to do this.  You can see already why the learning curve can be steep, especially if you haven’t come across this pattern before.

So today I googled “I don’t understand dependency injection” and got this fantastic explanation by Kevin William Pang.  I found that really helpful, and I’m sold.  I’d been wondering how the hell I was supposed to unit-test some of my more complex client code anyway… If you’re one that, like me, hasn’t understood this concept in much detail: his article is well worth a read, I won’t bother to try and explain it here.

But, I’m still not sure where the fancy dependency injection tools and frameworks come in.  I see the value in it, and I think “injecting” it into the constructor by using arguments given to the constructor seems just fine.  Meanwhile, the tools which are supposed to help, such as SwiftSuspenders or Minject seem to me to be really verbose, and not offer a lot more than the constructor method.

Maybe that style is more relevant for gaming.  Or maybe it’s benefits show up with more complex projects.  Or maybe I just haven’t been enlightened.

Either way, I’ll try to get enlightened… I think it’s worth spending time learning these patterns.  They’ve obviously gained traction for a reason, and a lot of better developers than me swear by them, so I’ll try wrap my head around it.  Maybe one day it’ll seem as clear to me as MVC, or even OOP do now (both of which took me a while at first).

If you have any suggestions / comments / explanations – I’d love to hear them in the comments section.

Categories
Haxe

Haxe3 Features: Variable Substitution in Haxe3 (aka String Interpolation)

One of my favourite features in the upcoming Haxe3 is also one of the simplest: String Interpolation (also called variable substitution).  If you were using Std.format() in Haxe2, you’ll recognise it.  It lets you do this:

var name = "Jason";
var age = 25;
trace ('My name is $name, I am $age years old.');
// My name is Jason, I am 25 years old

The first point to make is that it is triggered by using single quotation marks (‘), rather than double (“).  If you use double quotes, everything is treated as a plain string:

trace ("My name is $name, I am $age years old.");
// My name is $name, I am $age years old

The next point to make is that this all happens at compile time.  So the trace we made above, in Javascript, would output as:

console.log("My name is " + name + ", I am " + age + " years old");

So you can only do this with strings you have at compile time, as you’re writing the code.  If you want Strings that are given at runtime to have variable interpolation, you should use a templating library like erazor.

Now a few other things to note:

  1. If you want to put in a normal dollars sign, you can use two $, like this:
    trace ('The item costs $20');
    // "20" is not a valid variable name, so it is ignored.
    // Same as ("The " + item + " costs $20");
    
    trace ('That price is in $USD');
    // Error: Unknown Identifier "USD"
    trace ('That price is in $$USD');
    // Same as ("That price is in $" + "USD");
    
    var cost = 25;
    trace ('That item costs $$$cost');
    // The first two "$" are for the literal sign, the third is part of the variable.
    // Same as ("That item costs $" + cost);
  2. If you want to access anything more than a straight variable, use curly brackets:
    // Property access
    trace ('My name is ${user.name} and I am ${user.age} years old.');
    // Same as: "My name is " + user.name + " and I am " + user.age + " years old.";
    // Outputs: My name is jason and I am 25 years old.
    
    // A simple haxe expression
    trace ('$x + $y = ${x + y}');
    // Same as: "" + x + " + " + y + " = " + (x + y);
    // Outputs: 1 + 2 = 3
    
    // A function call 
    trace ('The closest Int to Pi is ${Math.round(3.14159)}');
    // Same as: "The closest Int to Pi is " + Math.round(3.14159);
    // Outputs: The closest Int to Pi is 3
  3. There is no HTML escaping, so be careful:
    var bold = "<b>Bold</b>";
    trace ('<i>Italic</i> $bold');
    // <i>Italic</i> <b>Bold</b>
    
    var safeBold = StringTools.htmlEscape("<b>Bold</b>");
    trace ('<i>Italic</i> $safeBold');
    // <i>Italic</i> &lt;b&gt;Bold&lt;/b&gt;
    
    var safeEverything = StringTools.htmlEscape('<i>Italic</i> $bold');
    trace (safeEverything);
    // &lt;i&gt;Italic&lt;/i&gt; &lt;b&gt;Bold&lt;/b&gt;

There you have it: String Interpolation, one of the most helpful (and easy to comprehend) features of the upcoming Haxe3 release.

Categories
Haxe

Mapping any SSH Server to a Network Drive in Ubuntu

My friend Justin showed me a cool trick this week – mapping any SSH server as a network drive in Ubuntu.  This is really useful for web development, where you have a whole bunch of servers that you have to connect to, transfer files to and from, and make small edits.

The integration is pretty seamless – it shows up in my file browser (just like a local USB drive), I can open files in any app I want, and every time I save the changes are synced back.  Pretty cool.

Here’s how:

  1. Open your Home Folder
  2. In the menu, choose “File -> Connect to Server”
  3. Change the type to “SSH”
  4. Enter the address of your server.
    eg. myvps.mydomain.com or 192.168.1.5
  5. Enter your username and password.
    (Note: If you have public / private keys set up, just enter the username.)
  6. Click Connect

This all comes built in with Ubuntu 12.04.

This is me browsing files on an Amazon EC2 instance, opening a few of them and editing them. Sweet!

Categories
Software Engineering

We could have had a great time together

We could have had a great time together.
Instead, you tried to sell me something.

Comment by “Gulliver” on “Creating Passionate Users” blog.

Categories
Edtech Haxe

A new project: OurSchoolDiary

So I’m working on a new project that has been brewing in my mind for a while. I’m going to aim to have a working prototype by the end of August, have users beta testing through till December and hopefully have my first paying clients by next year.

A screenshot of some of the first code for the project.

What is it?

The App is called “OurSchoolDiary”. It lets each school create their own School Diary app, where students can sign up and keep track of their homework, assignments and tests. The big win over competing solutions is that here, when the teacher adds an assessment or task, it automatically shows up in the students diary. We’re helping even unorganised students stay on top of their work.

On top of that, we’ll let parents receive emails informing them of their child’s progress. This way parents and teachers can work together to make sure they support their child’s education as much as possible.

And the final advantage, the school gets to show off how cutting-edge they are because they get their own “app”.  Logo and everything!

A Blog

As I go, I hope to keep track of my progress on this blog. (I’ll post to this category specifically, so you can subscribe by RSS).

Why keep a blog?

  • For the history, in case it is ever significant
  • For my own reflection and understanding, regardless of if it is a success.
  • To show off some cool technologies I’m using:
    • Web Apps – I’m not aiming for distribution through the App Store, I’m going a full HTML stack. Not even a hybrid using PhoneGap. This is a page you can view in a browser, and use offline, and the experience will be identical.
    • Haxe – this is a sweet programming language that lets you target Flash, Javascript, PHP, Java, C#, C++ and a platform called Neko. Up until now it’s main success has been in the indie-games market, but I believe it is mature enough to work for a full web-based productivity app.  Client and server. We’ll find out how that goes!
  • To look back on my decision making processes after we’ve launched, and see if my thinking was accurate.
  • To raise interest in the project
  • To explore some of the topics I find fascinating:
    • Usability
    • Design
    • New Marketing
    • Business Strategy
    • Contribution to the community
    • And a few more…

That’s all for now. I’ll try submit a couple of posts a week (at least) until I get this thing off the ground.