Categories
Faith Personal

Get Analoguer This Advent

(Disclaimer: My startup journey and my faith overlap in this post. For those of you who want to avoid the theology stop reading now!)

I’m almost at the end of PhDo, a 6 week startup night class that I have been LOVING. One of the key lessons has been about getting your idea started in the quickest, cheapest, fastest way possible.

The idea is that if you wait too long, you work on your idea in secret, you never put it in front of customers, it’s just an idea. You don’t know if it’s something they’ll want or need or appreciate. Until you reach out and touch a human being, you might as well not have done anything.

Sam, the guy running the course, coined a word. Rather than planning a digital masterpiece of an app that might take years to build, is there a simple, manual, analogue way you can solve the same problem for the same person, now.  Not once you have all the resources and the app and the staff team and investment and… No. Can you help meet a need today? Start meeting a need now, help someone out, see if it’s well received, then worry about scaling the solution up for more people.

Get analoguer. Get dirty. Get doing – solve a problem today. Scale later.

I did this wrong with my School Management System app. I never met with the staff, and completely underestimated how complex the problem of tracking student attendance is.  My solution was way too simplistic, and would never be adequate. The project blew out by 10 months and caused a lot of frustration as a result.

I tried to be a messiah and solve this problem, thinking it would be easy.  But I never entered in and felt / understood the pain first. How can you offer help if you have not stood with people and felt their pain and understood the complexity of the problem first?

This is the difference with how Jesus chose to work. He could try solve the world’s problems from in Heaven. Or send some prophet to do the dirty work. Instead he chose to get dirty, get personal, and get in touch with those he was trying to help. Understand their pain and show his solidarity, feel the full weight and complexity of the problem, and show those facing it that you are eager to help, in any way you can, even if you get dirty doing so. Even if it means suffering with them. Even if it means dying with them.

Jesus left the ivory tower of Heaven. He was God, but put his rights as God and abilities as God behind him, he became an ordinary human, wrapped in ordinary human flesh. He got analogue.

Today is the first day of Advent – the season where we anticipate the coming of Jesus to earth, culminating in Christmas.

We join Mary in expecting the birth of the baby Messiah, the God who gave it all up to come and understand our problems and join us in this often-painful world, and resolved to help us in any way he could, no matter the cost.

And we join with the people of faith around the world expecting the second time Jesus will come, having grasped the full complexity and pain of the human condition, and having felt it for himself, he’ll be back with a solution that scales.

Until then, let’s get analoguer and show love to people, not waiting for the perfect plan, strategy or opportunity, but starting right now in a way where you get as close to the problem as you can, and give what you can today, even if it’s not a full and perfect solution.

Categories
Personal Work Habits

Loved it, Loathed it

I’ve mentioned it a few times, but I’ve found Marcus Buckingham’s Standout profile and website really helpful.  The profile for me was accurate and insightful, and the tips I get sent each week are great.

One of them encouraged you to log the things in a week that you love (that leave you energized, strengthened) and the things that you loathed (that leave you drained, weakened).  This wasn’t about what other people do to you (a police officer gave me a fine – I loathed it, my boss gave me a pay rise, I loved it).  Rather this is about the work you’re doing, and what parts of your work energize you and what drains you.

Here’s my list.

Loved It

  • Working on new business strategy, or figuring out the brand/story that makes a new product have meaning.
  • Writing code for new APIs or frameworks that will be well designed, get use by many people, speed up development.  While I’m doing this I’m engaged, I’m learning and tweaking my skills, and I’m making something for that benefits both me and others.
  • Delivering a feature that has immediate customer benefit
  • Meeting people, getting them on board with a new idea.  This week it was a friend (and possibly future business partner), a learning support officer (who is an aspiring entrepreneur) and a friend who is wanting to get into graphic design.
  • Trying to consider how my faith world mixes with my business world.  Particularly this week: how can I see people as people, not resources or assets.  How can I help them find their particular spot in the world, and help them grow into it, rather than “how can I get you to do what I want”.
  • Wireframing, prototyping, design reference scouting

Loathed It

  • Maintaining old projects. Especially if it’s something I didn’t care for to begin. (For me this week, that includes Koha, Canvas, and Moodle to a lesser degree)
  • Being apart from Anna for too much of the week
  • Working on projects that feel like they will never end or progress.  I need a sense of momentum and an expectation that one thing will finish so that new things can start.
  • Having to report to (and problem solve with) a group of people who don’t understand the technical nature of the problem.
  • Having to answer questions where the “correct” answer is “drop quality, deliver faster”
  • Avoiding answering / helping people, because other deadlines are too heavy
  • Having to pretend something is good/ready when it’s not. I’d rather be honest. Drop projects if they suck, or at least admit it.

There’s my list for this week.  I’m in the middle of an extremely busy work season, so this is mostly focused on work and doesn’t touch much into my family life or faith life – both of which also have strengthening moments and weakening moments.  Still, a great exercise.

Categories
Haxe

Super Quick Haxe Abstracts Example

I just posted a quick gist to the Haxe mailing list showing how one way that abstracts work.

They’re a great way to wrap a native API object (in this case, js.html.AnchorElement) without having to create a new wrapper object every single time. Which means they’re great for performance, the end result code looks clean, and thanks to some of the other abstract magic (implicit casts, operator overloading etc) there is a lot of cool things you can do.

Have a look at the sample, read the Haxe manual, and let me know what you think or if you have questions :)

Categories
Personal

Unsolicited Emails from Australian Labor

I just sent an email abuse report to MailChimp, documenting the unsolicited emails I have been receiving from the Australian Labor party.  I understand that one of their members may have accidentally entered the wrong email address once, but it is unfair that they have subscribed me to 8 separate email lists so far, and I have to take the time to unsubscribe from each one – when I never subscribed in the first place.  This is illegal under the SPAM ACT 2003.

Here is the email I sent them:

Hi

In Australia we have 2 main political parties, one of them being Labor. They’ve recently been voting for a new leader. I’m not a member of the party, but I’ve received an email from Labor people almost every week for the last month – all from different lists, and I have unsubscribed every single time, choosing the “I never subscribed” option.

5 of the 8 lists I received unsolicited email from were hosted by MailChimp, the remainder by NationBuilder (good luck competing! As a web developer I like your product better)

EMAIL 1
Subject: Party. Policy. People.
Sender: MailChimp
X-campaignid: mailchimpd1d04c8e8a8375877ba044bc4.be6aae17ed

EMAIL 2
Subject: Why I’m Standing
Sender: NationBuilder

EMAIL 3
Subject: I want to make a difference
Sender: NationBuilder

EMAIL 4
Subject: Join Bill Shorten for a conversation with country members tonight
Sender: MailChimp
X-campaignid: mailchimp2a0336f66d93a2c444ff3d779.ed092fdc95

EMAIL 5
Subject: Make your vote count
Sender: NationBuilder

EMAIL 6
Subject: I’m supporting Bill
Sender: MailChimp
X-campaignid: mailchimpd1d04c8e8a8375877ba044bc4.1636a97be2

EMAIL 7
Subject: Labor eNews
Sender: MailChimp
X-campaignid: mailchimpb6a6fa942a4870ed76b06bc02.4f94c686b5

EMAIL 8
Subject: Thank you for your support
Sender: MailChimp
X-campaignid: mailchimp429f4375fe72549c8e09fe0fd.53fef0c08a

As you can see, the Australian Labor party is creating many different lists, and is subscribing my email address to each of them without my permission. I am assuming another Jason O’Neil entered an incorrect email address (this happens often), but as it stands I can only assume the Labor party is importing a bulk list of email addresses into MailChimp, and while I can unsubscribe from each individual mailing list, they will just create new lists and re-import my address.

Unsolicited email is illegal in Australia under the SPAM ACT 2003. I have attempted to contact them but was unable to resolve the issue, and I have received multiple emails since then.

I guess what I am asking:

– Can you contact the owners of these lists and remind them of their responsibilities under law and under your terms and conditions?

– Is there a way to prevent my address from being imported into new lists during a bulk import?

Thank you for your time!
Jason

Categories
Faith Justice and Politics Personal

Human Faces

When I see the human face behind a political issue, the emotions of apathy, indignation or anger become less.  Then empathy (understanding their suffering), sorrow (grieving with them), remorse (that collectively, the humans in my country did this to other humans) – these emotions become stronger.  Finally, there is hope – these people have courage, and see a better future.  They want to fight injustice, and fight for the rights of those who follow.  I hope, at the end of my life, I can say that I partnered with these guys, not the powers that locked them up and stole their childhood.

Refugee looks back on ordeal of seeking asylum and being detained in Nauru

(God, have mercy, do not treat us as our sins deserve.)

Categories
Edtech

Humans of New York (reblog)

Wow, just wow.

I struck up a conversation with him, and he casually mentioned that he was having trouble adjusting to Columbia, due to his “previous situation.” So I asked him to elaborate.

“I was born in Egypt,” he said. “I worked on a farm until 3rd grade with no education. I came to the US for one year, started 4th grade, but was pulled out because my father couldn’t find work and returned to Egypt for a year. The first time I went to an actual school was middle school, but the whole school was in one classroom, and I was working as a delivery boy to help the family. It was illegal for me to be working that young, but I did. When I finally got into high school, my house burned down. We moved into a Red Cross Shelter, and the only way we could live there is if we all worked as volunteers. I got through high school by watching every single video on Khan Academy, and teaching myself everything that I had missed during the last nine years. Eventually I got into Queens College. I went there for two years and I just now transferred to Columbia on a scholarship provided by the New York Housing Association for people who live in the projects. It’s intimidating, because everyone else who goes to Columbia went to the best schools, and have had the best education their entire lives.”

 

From: Humans of New York

Categories
Faith Personal Reading & Inspiration

I’m not lapsed. I am a Catholic in waiting — waiting for my church to remember the Gospels, to be a justice and peace-seeking community, to be fully inclusive of women and to be welcoming to people who are not hetero-normative.

Read more: What should church look like

Categories
Edtech Faith Personal

Redefining Entrepreneurship

I want to be an Entrepreneur.  So do a lot of people these days.

It’s been made famous by the likes of Steve Jobs, Bill Gates, and Mark Zuckerburg and more recently startups like AirBNB, DropBox, Instagram and Roxio (Angry Birds) have painted the vivid portrait of the glorious life of a founder: working on something you’re passionate about, creating wealth, pleasing users and making your mark on the world.

People like Paul Graham, whose startup school “Y-Combinator” has funded over 800 startups, argue strongly that startups are the best model for business and innovation, and I tend to agree.  They also point out how hard it all is.

While on holiday, I was thinking about what it means to live subversively – inside one world, with it’s values (being cool, making money, making a mark on the world) while belonging to another reality (living selflessly, trying to bring justice, hope and love into the world, trusting God to help you do things you couldn’t do on your own).

For most people, startups are about one of these things:

  1. Making your mark on the world (“leaving a dent in the universe”, to quote Steve Jobs)
  2. Making a lot of money very quickly
  3. Getting paid to do something you love doing
  4. The thrill of doing something risky.  Not choosing a boring life.

I have no problem with any of these motivations, other than the possible vanity and self absorption that could come with success.  But I wanted to think about what the drive is to run a startup when you come at it from a Christian world-view.

I came up with this line:

“An Exploration of Grace”

(Note: this was an unpublished draft from September 2013. I had a few extra sentences and probably intended to write more, but I can’t remember where it was going. Publishing this in 2023, a decade later, I love this line and will choose to leave it there, and let the sentence speak for itself and evoke what it will).

Categories
Personal Work Habits

How to get the best work out of me

According to Marcus Buckingham’s StandOut profile, this is how to get me doing my best work when I’m working with you:

I am resourceful and can fill the gaps quicker than most. If there’s a project to begin that lacks details or data, I can get it off to a good start.

Tell me that if I try to serve everyone I wind up serving no-one. I must make a choice about who to serve well, and then serve them well. Know that I will be sensitive to any criticisms.

If you’d like to grab my attention, tell me I am not moving boldly enough. Tell me that you expect me to be the first person to challenge an existing way of doing things, the first person to spot, bump into, and report back on a new threat, or a new opportunity.

The overall StandOut profile was disturbingly accurate for me and a friend who took it with me, and this tip also resonates strongly.  I would recommend the profile to anyone seeking to understand their work self better, and I’d recommend this advice to people trying to work better with me :)

Categories
Haxe

Web.cacheModule and Expiring DB connections

The Story

A while ago I posted about neko.web.cacheModule, a way to make your site run dramatically faster on mod_neko or mod_tora. After spending some time making ufront compatible with this mode of running, I was excited to deploy my app to our schools with the increased performance.

I deployed, ran some tests, seemed happy, went home and slept well. And woke up the next morning to a bunch of 501 errors.

The Error

The error message was coming from the MySQL connection: “Failed to send packet”.

At first I just disabled caching, got everyone back online, and then went about trying to isolate the issue. It took a while before I could reproduce it and pinpoint it. I figured it was to do with my DB connection staying open between requests, thanks to the new module caching.

A google search showed only one Haxe related result – someone on IRC that mentioned when they sent too many SQL queries it sometimes bombed out with this error message. Perhaps leaving it open eventually overran some buffer and caused it to stop working? Turns out this was not the case, I used `ab` (Apache Benchmark tool) to query a page 100,000 times and still didn’t see the error.

Eventually I realised it was to do with the MySQL Server dropping the connection after a period of inactivity. The `wait_timeout` variable was set to 28800 by default: so after 8 hours of inactivity.  So long enough that I didn’t notice it the night before, but short enough that the timeout occured overnight while all the staff were at home or asleep… So the MySQL server dropped the connection, and my Haxe code did not know to reconnect it. Whoops.

The Solution

I looked at Nicolas’s hxwiki source code, which runs the current Haxe site for some inspiration on the proper way to approach this for `neko.Web.cacheModule`. His solution: use http://api.haxe.org/sys/db/Transaction.html#main. By the looks of it, this will wrap your entire request in an SQL transaction, and should an error be thrown, it will rollback the transaction. Beyond that, it will close the DB connection after each request. So we have a unique DB connection for each request, and close it as soon as the request is done.

My source code looks like this:

class Server
{
  static var ufApp:UfrontApplication;

  static function main() {
    #if (neko && !debug) neko.Web.cacheModule(main); #end
    
    // Wrap all my execution inside a transaction
    sys.db.Transaction.main( Mysql.connect(Config.db), function() {
      init();
      ufApp.execute();
    });
  }

  static function init() {
    // If cacheModule is working, this will only run once
    if (ufApp==null) {
      UFAdminController.addModule( "db", "Database", new DBAdminController() );
      ufApp = new UfrontApplication({
        dispatchConfig: Dispatch.make( new Routes() ),
        remotingContext: Api,
        urlRewrite: true,
        logFile: "log/ufront.log"
      });
    }
  }
}
Categories
Faith Personal

My Life’s Work

Here is my servant whom I have chosen
the one I love, in whom I delight;
I will put my Spirit on him,
and he will proclaim justice to the nations.
He will not quarrel or cry out;
no one will hear his voice in the streets.
A bruised reed he will not break,
and a smoldering wick he will not snuff out,
till he leads justice to victory.
In his name the nations will put their hope.

Matthew 12:18-21

—–

my servant

Jesus was a servant, and as his disciples, we are his.  Have no illusions, we are here to serve, not to be served.

I have chosen

Each person chosen and assigned their role in ushering in God’s Kingdom, according to their unique God-given skills, strengths and gifts.

I love

Our strength and courage draws on this love God has for us.

in whom I delight

Our motivation is his delight.  Not to earn it, but to revel in it and enjoy it and immerse ourselves in it.

my Spirit on him

This isn’t merely natural work and effort, this is work empowered and affirmed by God’s Holy Spirit.

proclaim justice

Equality, fairness, hope, safety, opportunity

will not quarrel or cry out

It’s not about the sport, spectacle or stardom of society’s idea of success.

no one will hear his voice

Less talk, more action.  Less brand and perception and posturing, more life change.

bruised reed… smoldering wick

The hurt, oppressed, poor, hopeless and helpless, sick, overlooked.

till

Mercy is the strategy and the game plan.  We hold to the strategy until the end.

leads justice to victory

Justice will win out, but it’s slow and requires action, leadership.

In his name the nations will put their hope

This is my life’s work:

to offer Jesus’ hope to all that you can,
to work as he did,
empowered as he was,
with the values he carried
and the strategy he adopted
to the same end he strived for:
   the victory of justice,
   the hope of the nations,
   the delight of the Father.

Categories
Haxe Haxe Log

My Haxe Log: Week #2

This week:

  • My token one day a week I continued on my Node-Webkit project.  This time I made externs for Kue (externs, which appear to be working) and FFMpeg (externs, not functional just yet).  Still enjoying working with Node-Webkit, and with the Node-API library especially.  Sad I didn’t get to make more progress on it this week.
  •  Ufront:
      • Make tracing / logging work reliably between multiple requests. After enabling neko.Web.cacheModule(), I began to find areas where Ufront was not very multiple-request-friendly. These would have surfaced later with a port to Client JS or Node JS, but it’s good to find them now.One problem was that our tracing and logging modules were behaving as if there was only one request at a time. This could result in a trace message for one request ending up being output to somebody else’s request, which is obviously bad.

        The problem is a tricky one, as trace() always translates to haxe.Log.trace(), and you with Ufront’s multiple-request-at-a-time design, you can’t know which request is the current one from a static method. If I think of a clever way to do it, possibly involving cookies and sessions, then I might include a HttpContext.getCurrentContext() static method. This would probably have to be implemented separately for each supported platform.

        The solution for now, however, was to not keep track of log messages in the TraceModule, but in the HttpContext. Then on the onLogRequest event, the trace modules get access to the log messages for the current context, and can output them to the browser, to a file, or whichever they choose.

        The downside is that you have to use httpContext.ufTrace() rather than trace(). I added a shortcut for this in both ufront.web.Controller and ufront.remoting.RemotingApiClass, so that in your controllers or APIs you can call uftrace() and it will be associated with the current request. There is also ufLog, ufWarn and ufError.

        I also made RemotingModule work similarly with tracing and logging – so logs go to both the log file and the remoting call to the browser.

      • Fix logging in ErrorModule. One of the things that made debugging the new ufront really hard was that when there was an Error, the ErrorModule displayed, but the trace messages did not get sent to the browser or the log file. I did a bit of code cleanup and got this working now.
      • Fixed File Sessions / EasyAuth. Once able to get my traces and logs working more consistently, I was able to debug and fix the remaining issues in FileSession, so now EasyAuth is working reliably, which is great.
      • Added Login / Logout for UF-Admin. With UF-Admin, I added a login screen and logout, that works with EasyAuth for now. I guess I will make it pluggable later… For now though it means you can set up a simple website, not worry about auth for the front end, but have the backend password protected. If you use EasyAuth for your website / app, the same session will work on the ufadmin page.
      • Created uf-content for app-generated files. I moved all app-generated files (sessions, logs, temp files etc) into a folder called “uf-content”. Then I made this configurable, and relative to httpContext.request.scriptDirectory. You can configure it by changing the contentDirectory option in your UfrontConfiguration. This will make it easier when deploying, we can have instructions to make that single directory writeable but not accessible via the web, and then everything that requires FileSystem access can work reliably from there.
      • Pushed new versions of the libraries. Now that the basics are working, I pushed new versions of the libraries to Haxelib. They are marked as ufront-* with version 1.0.0-beta.1. From here it will be easy to update them individually and move towards a final release.
      • Demo Blog App. To demonstrate the basics of how it works, and a kind of “best practices” for project structure, I created a demo app, and thought I would start with a blog. I started, and the basic setup is there, including the config structure and each of the controller actions, and the “ufadmin” integration. But it’s not working just yet, needs more work.
      • Identified Hair website. I have a website for a friend’s small business that I’ve been procrastinating working on for a long time. On Saturday I finally got started on it, and set up the basic project and routes in Ufront. In about 4 hours I managed to get the project set up, all the controllers / routes working, all the content in place and a basic responsive design with CSS positioning working. All the data is either HTML, Markdown or Database Models (which get inserted into views). Once I’ve got their branding/graphics included, I’ll use ufront to provide a basic way to change data in their database. And then if they’re lucky, I might look at doing some Facebook integration to show their photo galleries on the site.
Categories
Faith Personal

A Really Clean House

Imagine being married to someone who was absolutely intent on providing a nice home for you.  And by “intent”, I mean obsessive.  They clean everyday – and not just tidy, but dust, mop, scrub and disinfect, and then put nice smelling candles everywhere.  They constantly decorate and set things up just the way you like it.  They maintain the garden keep the yard orderly.  They put on an amazing dinner everyday, starting it early so that it finishes right on time as you get home.

And then the moment you walk through the door, they head off to their own section of the house.  No welcome, no eye contact, no hugs, no acknowledgement at all.  For the rest of the night, you try to enjoy the beautifully pristine house on your own.  Apparently they do it because they love you.  But you can’t help but feel if they really loved you they’d at least want to see you, talk to you, spend time with you and touch you.  The service is there, and it’s great – as good as you’d get in a hotel.  But, much like the hotel, this is not love, it’s not a relationship, it’s just service.

I imagine this is how God feels about people who are too busy being religious to spend time getting to know him.

For I desire mercy, not sacrifice.  And acknowledgement of God rather than burnt offerings.
Hosea 6:6

Categories
Haxe Haxe Log

My Haxe Log: Week #1

Hello! For a reason I can’t comprehend, this page is the most visited page on my blog. If you’re looking for information about logging in Haxe, the “Logging and Tracing” page in the manual is a good start.

If you can be bothered, leave a comment and let me know what you’re looking for or how you came to be here. I’d love to know!

Jason.

Every week as part of my work and as part of my free time I get to work on Haxe code, and a lot of that is contributing to libraries, code, blog posts etc.  Yesterday was one of those frustrating days where I told someone I’d finish a demo ufront app and show them how it works, but I just ran into problem after problem and didn’t get it done, and was feeling pretty crap about it.

After chatting it out I looked back at my week and realised: I have done alot.  So I thought I should start keeping a log of what I’ve been working on – mostly for my own sake, so I can be encouraged by the progress I have made, even if I haven’t finished stuff yet.  But also in case anything I’m working on sparks interest or discussion – it’s cool to have people know what I’m up to.

So I’d like to start a weekly log.  It may be one of those things I do once and never again, or it may be something I make regular: but there’s no harm in doing it once.

So here we go, my first log.  In this case, it’s not just this week, some of it requires me to go back further to include things I’ve been working on, so it’s a pretty massive list:

  • Node Webkit: On Monday’s I work at Vose Seminary, a tertiary college, and I help them get their online / distance education stuff going.  Editing videos, setting up online Learning Management Systems etc.  I have a bunch of command line utils that make the video editing / exporting / transcoding / uploading process easier, but I want to get these into graphics so other staff can use it.  Originally I was thinking of using OpenFL / StablexUI.  I’m far more comfortable with the JS / Browser API than the Flash API however, and so Node-Webkit looked appealing.  On Monday I made my first Haxe-NodeJS project in over a year, using Clement’s new Node-API repo.  It’s beautiful to work with, and within an hour and a half I had written some externs and had my first “hello-world” Node-Webkit app.  I’ll be working on it again this coming Monday.
  • neko.Web.cacheModule: I discovered a way to get a significant speed-up in your web-apps.  I wrote a blog post about it.
  • Ufront: I’ve done a lot of work on Ufront this week.  After my talk at WWXthis year, I had some good chats with people and basically decided I was going to undertake a major refactor of ufront.  I’m almost done!  Things I’ve been working on this week (and the last several weeks, since it all ties in together):
    • Extending haxe.web.Dispatch (which itself required a pull request) to be subclassed, and allowing you to 1) execute the ‘dispatch’ and ‘executeAction’ steps separately and 2) allow returning a result, so that you can get the result of your dispatch methods.  This works much nicer with Ufront’s event based processing, and allows for better unit testing / module integration etc.  The next step is allowing dispatch to have asynchronous handlers (for Browser JS and Node JS).  I began thinking through how to implement this also.
    • After discovering neko.Web.cacheModule, I realised that it had many implications for Ufront.  Basically: You can use static properties for anything that is generic to the whole application, but you cannot use it for anything specific to a request.  This led to several things breaking – but also the opportunity for a much better (and very optimised) design.
    • IHttpSessionState, FileSession: the first thing that was broken was the FileSession module.  The neko version was implemented entirely using static methods, which led to some pretty broken behaviour once caching between requests was introduced.  In the end I re-worked the interface “IHttpSessionState” to be fairly minimal, and was extended by the “IHttpSessionStateSync” and “IHttpSessionStateAsync” interfaces, so that we can begin to cater for Async platforms.  I then wrote a fresh FileSession implementation that uses cookies and flat-files, and should work across both PHP and Neko (and in Future, Java/C#).  The JS target would need a FileSessionAsync implementation.
    • IAuthHandler / EasyAuth: At the conference I talked about how I had an EasyAuth library that implemented a basic User – Group – Permission model.  At the time, this also was implemented with Static methods.  Now I have created a generic interface (IAuthHandler) so that if someone comes up with an auth system other than EasyAuth, it can be compatible.  I also reworked EasyAuth to be able to work with different a) IHttpSessionState implementations and b) different IAuthAdapter’s – basically, this is an interface that just has a single method: `authenticate()`.  And it tells you if the user is logged in or not.  EasyAuth by default uses EasyAuthDBAuthAdapter, which compares a username and password against those in the database.  You could also implement something that uses OpenID, or a social media logon, or LDAP, or anything.  All this work trying to make it generic enough that different implementations can co-exist I think will definitely pay off, but for now it helps to have a well thought out API for EasyAuth :)
    • YesBoss: Sometimes you don’t want to worry about authentication.  Ufront has the ability to create a “tasks.n” command line file, which runs tasks through a Command Line Interface, rather than over the web.  When doing this, you kind of want to assume that if someone has access to run arbitrary shell commands, they’re allowed to do what they want with your app.  So now that I have a generic interface for checking authentication, I created the “YesBossAuthHandler” – a simple class that can be used wherever an authentication system is needed, but any permission check it always lets you pass.  You’re the boss, after all.
    • Dependency Injection: A while ago, I was having trouble understanding the need for Dependency Injection.  Ufront has now helped me see the need for it.  In the first app I started making with the “new” ufront, I wanted to write unit tests.  I needed to be able to jump to a piece of code – say, a method on a controller – and test it as if it was in a real request, but using a fake request.  Dependency injection was the answer, and so in that project I started using Minject.  This week, realising I had to stop using statics and singletons in things like sessions and auth handling, I needed a way to get hold of the right objects, and dependency injection was the answer.  I’ve now added it as standard in Ufront.  There is an `appInjector`, which defines things that should be injected everywhere (modules, controllers, APIs etc).  For example, injecting app configuration or a caching module or an analytics API.  Then there is the dispatchInjector, which is used to inject things into controllers, and the remotingInjector, which is used to inject things into APIs during remoting calls.  You can define things you want to make available at your app entry point (or your unit test entry point, or your standalone task runner entry point), and they will be available when you need them.  (As a side note, I now also have some great tools for mocking requests and HttpContexts using Mockatoo).
    • Tracing: Ufront uses Trace Modules.  By default it comes with two: TraceToBrowser and TraceToFile.  Both are useful, but I hadn’t anticipated some problems with the way they were designed.  In the ufront stack, modules exist at the HttpApplication level, not at the HttpRequest level.  On PHP (or uncached neko), there is little difference.  Once you introduce caching, or move to a platform like NodeJS – this becomes a dangerous assumption.  Your traces could end up displaying on somebody else’s request.  In light of this, I have implemented a way of keeping track of trace messages in the HttpContext.  My idea was to then have the Controller and RemotingApiClass have a trace() method, which would use the HttpContext’s queue.  Sadly, an instance `trace()` method currently does not override the global `haxe.Log.trace()`, so unless we can get that fixed (I’m chatting with Simon about it on IRC), it might be better to use a different name, like `uftrace()`.  For now, I’ve also made a way for TraceToBrowser to try guess the current HttpContext, but if multiple requests are executing simultaneously this might break.  I’m still not sure what the best solution is here.
    • Error Handling: I tried to improve the error handling in HttpApplication.  It was quite confusing and sometimes resulted in recursive calls through the error stack.  I also tried to improve the visual appearance of the error page.
    • Configuration / Defaults:The UfrontApplication constructor was getting absurd, with something like 6 optional parameters.  I’ve moved instead to having a `UfrontConfiguration` typedef, with all of the parameters, and you can supply, all, some or none of the parameters, and fall-backs will be used if needed.  This also improves the appearance of the code from:new UfrontApplication( true, “log.txt”, Dispatch.make(new Routes()) );

      to

      new UfrontApplication({
      urlRewrite: true,
      dispatchConf: Dispatch.make( new Routes() ),
      logFile: “log.txt”
      });

    • More ideas: last night I had trouble getting to sleep.  Too many ideas.  I sent myself 6 emails (yes 6) all containing new ideas for Ufront.  I’ll put them on the Ufront Trello Board soon to keep track of them.  The ideas were about Templating (similar abstractions and interfaces I have here, as well as ways of optimising them using caching / macros), an analytics module, a request caching module and setting up EasyAuth to work not only for global permissions (CanAccessAdminArea), but also for item-specific permissions: do you have permission to edit this blog post?
    • NodeJS / ClientJS: after using NodeJS earlier in the week, I had some email conversations with both Clement and Eric about using Ufront on NodeJS.  After this week it’s becoming a lot more obvious how this would work, and I’m getting close.  The main remaining task is to support asynchronous calls in these 3 things: Dispatch action execution calls, HttpRemotingConnection calls, and database calls – bringing some of the DB Macros magic to async connections.  But it’s looking possibly now, where as it looked very difficult only 3 months ago.
  • CompileTime: I added a simple CompileTime.interpolateFile() macro.  It basically reads the contents of the file at macro time, and inserts it directly into the code, but it inserts it using String Interpolation, as if you had used single quotes.  This means you can insert basic variables or function calls, and they will all go in.  It’s like a super-quick and super-basic poor-man’s templating system.  I’m already using it for Ufront’s default error page and default controller page.
  • Detox: this one wasn’t this week, but a couple of weeks ago.  I am working on refactoring my Detox (DOM / Xml Manipulation) library to use Abstracts.  It will make for a much more consistent API, better performance, and some cool things, like auto-casting strings to DOM elements:”div.content”.find().append( “<h1>My Content</h1>” );
  • My Work Project: Over the last two weeks I’ve updated SMS (my School Management System project, the main app I’ve been working on) to use the new Ufront.  This is the reason I’ve been finding so much that needs to be updated, especially trying to get my app to work with “ufront.Web.cacheModule”.
Categories
Haxe

neko.Web.cacheModule()

Until now I haven’t had to worry much about the speed of sites made using Haxe / Ufront,  – none of the sites or apps I’ve made have anywhere near the volume for it to be a problem, and the general performance was fast enough that no one asked questions. But I’m going to soon be a part of building the new Haxe website, which will have significant volume.

So I ran some benchmarks using ab (Apache’s benchmarking tool), and wasn’t initially happy with the results. They were okay, but not significantly faster than your average PHP framework. Maybe I would have to look at mod_tora or NodeJS for deployment.

Then I remembered something: a single line of code you can add that vastly increases the speed: neko.Web.cacheModule(main).

Benchmarks

Here is some super dumb sample code:

class Server {
  static var staticInt = 0;
  static function main() {
    #if neko
      neko.Web.cacheModule(main); // comment out to test the difference
    #end 
    var localInt = 0; 
    trace ( ++staticInt ); 
    trace ( ++localInt ); 
  } 
} 

And I am testing with this command:

ab -n 1000 -c 20 http://localhost/ 

Here are my results (in requests/second on my laptop):

  • Apache/mod_php (no cache): 161.89
  • NekoTools server: 687.49
  • Apache/mod_neko (no cache): 1054.70
  • Apache/mod_tora (no cache): 745.94
  • Apache/mod_neko (cacheModule): 3516.04
  • Apache/mod_tora (cacheModule): 2185.30

First up: I assume mod_tora has advantages on sites that use more memory, but a dummy sample like this is more overhead than it’s worth.

Second, and related: I know these tests are almost worthless, we really need to be testing a real app, with file access and template processing and database calls.

Let’s do that, same command, same benchmark parameters:

  • Apache/mod_php (no cache): 3.6 (ouch!)
  • NekoTools server: 20.11
  • Apache/mod_neko (no cache): 48.74
  • Apache/mod_tora (no cache): 33.29
  • Apache/mod_neko (cacheModule): 351.42
  • Apache/mod_tora (cacheModule): 402.76

(Note: PHP has similar caching, using modules like PHP-APC. I’m not experienced setting these up however, and am happy with the neko performances I’m seeing so I won’t investigate further)

Conclusions:

  • the biggest speed up (in my case) seems to come from cacheModule(), not mod_tora. I believe once memory usage increases significantly, tora brings advantages in that arena, and so will be faster due to less garbage collection.
  • this could be made faster, my app currently has very little optimisation:
    • the template system uses Xml, which I assume isn’t very fast.
    • a database connection is required for every request
    • there is no caching (memcached, redis etc)
    • I think I have some terribly ineffecient database queries that I’m sure I could optimise
  • Ufront targeting Haxe/PHP is not very fast out-of-the-box. I’m sure you could optimise it, but it’s not there yet.
  • This is running on my laptop, not a fast server. Then again, my laptop may be faster than a low end server, not sure.

Usage

So, how does it work?

#if neko neko.Web.cacheModule( main ); #end 

The conditional compilation (#if neko and #end) is just there so that you can still compile to other targets without getting errors. The cacheModule function has the following documentation:

Set the main entry point function used to handle requests.
Setting it back to null will disable code caching.

By entry point, it is usually going to mean the main() function that is called when your code first runs. So when the docs ask for a function to use as the entry point, I just use main, meaning, the static function main() that I am currently in.

I’m unsure of the impact of having multiple “.n” files or a different entry point.

The cache is reset whenever the file timestamp changes: so when you re-compile, or when you load a new “.n” file in place.

If you wanted to manually disable the cache for some reason, you use cacheModule(null). I’m not sure what the use case is for this though… why disable the cache?

Gotchas (Static variable traps with cacheModule)

The biggest gotcha is that static variables persist in your module. They are initialized just once, which is a big part of the speed increase. Let’s look at the example code I posted before:

class Server {
  static var staticInt = 0;
  static function main() {
    #if neko
      neko.Web.cacheModule(main); // comment out to test the difference
    #end 
    var localInt = 0; 
    trace ( ++staticInt ); 
    trace ( ++localInt ); 
  } 
} 

With caching disabled, both trace statements will print “0” every time. With caching enabled, the staticInt variable does not get reset – it initializes at 0, and then every single page load will continue to increment it, it will go up and up and up.

What does this mean practically:

  • If you want to cache stuff, put it in a static variable. For example:
    • Database connections: store them in a static variable and the connection will persist.
    • Templates: read from disk once, store them in a static variable
    • App Config, especially if you’re passing JSON or Xml, put it in a static and it stays cached.
  • Things which should be unique to a request, don’t store in a static variable. For example:
    • Ufront has a class called NekoSession, which was entirely static methods and variables, and made assumptions that the statics would be reset between requests. Wrong! Having the session cached between different requests (by different users) was a disaster – everytime you click a link you would find yourself logged in as a different user. Needless to say we needed to refactor this and not use statics :) To approach it differently, you could use a static var sessions:StringMap<SessionID, SessionData> and actually have it work appropriately as long as the cache stayed alive.
    • Avoid singletons like Server.currentUser, or even User.current – these static variables are most likely going to be cached between requests leading to unusual results.
Categories
Edtech Haxe

Cross post: Why the Pomodoro technique doesn’t work for me

In case you’re interested, on my Personal Blog I have a post “Why the Pomodoro Technique Doesn’t Work For Me”.  It’s about time management for creative workers.  Have a look if you’re interested…

Categories
Personal Work Habits

Why the Pomodoro technique doesn’t work for me

My friend Amanda writes a great blog over at Capture30Days. Her recent post “getting stuff done” outlines the Pomodoro technique: work for 25 minutes uninterrupted, take a 5 minute break, start again. I think it works great for some sorts of work.

It doesn’t work for me.

I had tried this technique, but I found for my sort of work it sometimes was in fact harmful.  I guess my work (designing educational apps) swings between product design (creative, collaborative) and programming (a different sort of creative, lots of problem solving, often on my own) and so I sometimes need to just work through a task list and have lots of interactions with others, and I sometimes need to have long periods of uninterrupted focus.

For the programming especially (and to an extent the design also), I have to work hard to get into a “flow” state, where I get the entire mental model of what I’m creating in my head, so that I can work and create efficiently, remembering how all of the different pieces of my app are supposed to fit together.  It can take me a couple of hours to get into this state.  And when I’m in this state, I don’t want to stop.

And knowing I have to stop, because my 25 minutes is up and it’s time for a 5 minute break, or because I have a meeting, or because it’s lunch time, can seriously throw me off.  I’m not the only one.  Paul Graham contrasts the “managers schedule” (1 hour blocks, optimised for meetings) and the “makers schedule” (usually blocks into “morning”, “afternoon” and “working into the night”, optimised for creative work).  He makes the point that for a creative, a single meeting can destroy a whole afternoon.  I definitely have experienced that.

So, alternative to the Pomodoro technique?  I personally go for the 1-3-5 technique.  It goes like this:

Today I will achieve:

  • 1 Big Things:
    _______________
  • 3 Medium Things
    _______________
    _______________
    _______________
  • 5 Small Things
    _______________
    _______________
    _______________
    _______________
    _______________

I find this gives me the flexibility I need to work on big tasks that require long periods of focus, as well as help me not forget the small things that also need doing.  In reality, a day may end up looking like this

  • Morning:
    Small task 1 – emails
    Small task 3 – voicemails and phone calls
    Small task 4 – fix small bug
    Medium Task 1 – draw interface designs for a new feature
  • Afternoon:
    Small Task 5 – responding to support questions
    Big Task – programming a new feature
    Medium Task 2 – got started finding a bug, did not finish.

If I’m having trouble getting into “the zone” or “flow”, I start with the small tasks and work my way up to the big ones.  If I get stuck on one task, I jump to a different one.  Then anything I don’t get done, goes on to the list for the next day.

Finally, there’s a website which makes this easy: http://1-3-5.com/  I set that site as my homepage, so every time I open a new tab, rather than Google or Facebook, I see my task list.

Do you have any tips for staying focused and managing your time when working on creative or programming projects?  Especially when you don’t have a formal workplace to keep you accountable :)

Categories
Faith Justice and Politics Personal

Cowards

“All right, but let the one who has never sinned throw the first stone!” Then he stooped down again and wrote in the dust.

When the accusers heard this, they slipped away one by one, beginning with the oldest, until only Jesus was left in the middle of the crowd with the woman.

I used to notice 3 groups here: the accusers, the accused, the defender. I had a hard time imagining which group I would realistically fall into.

I’m not often confronted and threatened for my errors, I’m not the sort to condemn others for theirs either. Yet I usually lack the courage to defend the accused and stand up to the crowd, so I can’t honestly group myself with Jesus in this story.

I guess I fit with the group I never noticed before today: the onlookers. The crowd, drawn into the drama, not sure of what they think, but afraid to speak up, lest they say something wrong and find themselves the new target of the accusers.

Categories
Faith

Lord, thank you for using the foolish to confound the wise and the weak ones to shame the strong.  Help us live with the shrewdness of serpents and the innocence of doves.  Keep our feet from fatigue, our spirits from despair, our hands from failing to love and our mouths from failing to sing in praise to you.  Amen.

Categories
Faith Personal

Smaller miracles

It was haunting last night to walk into the hospital and see my Grandpa.

I watched my Dad pray for his Dad. As a pastor he’s prayed for many people. It’s hard to pray for someone who may well be on their deathbed. I imagine it’s harder still when it’s your dad. “Father of mercies…” he prayed.

What mercy can you ask for? It felt too late to pray for a miracle. At that age, and with cancers already leaving visible scars all over the body, you only ask for small miracles. For relief from pain, for peace, for comfort for our family.

Yet even a healing at this late stage, miraculous as it would be, would only be a small miracle.

The bigger miracle is the one that already happened. In my 26 years I’ve only ever known my Gramps as fun loving, and family loving. When he’d play jokes on us, (which he did often, he loved it), his heart was always warm, and it was fun. It wasn’t always that way apparently. I don’t know the full story, but there was alcohol, there was aggression, and he was described, light on the details, as “not a very nice person”. Until Jesus changed him. A change in personality and in heart, of that magnitude, is not common. It’s a miracle, a redemptive act of God that took something broken and made it better, made it beautiful. It is no small miracle that I only ever knew the beautiful heart of my Grandpa.

The other miracle is that the next time I see my Grandpa, the cancer will be gone from his body, his face will be young again (younger and stronger and happier than I’ve ever seen). The fragile, hurting body I saw last night will be restored and perfected. And he’ll be with his wife Shirley again, surely as happy in that moment as in the moment captured in the wedding photo on our family room. And his kids. And us grandkids. The redemption of people: our bodies, our hearts, our relationships. That miracle is huge.

After walking out last night I struggled with finding the mercy in an old man suffering. And my faith for miraculous healings isn’t what it used to be. Today when I got the call from my Dad though, amidst the tears was a gratefulness, and a hopefulness, for the greater miracles.

Categories
Haxe

Language and API Design

Paul Graham has written some great essays over time, and most of them hold up surprisingly well as they age.  Take this article, “Five Questions About Language Design“.  Written in May 2001.  That’s over 12 years ago from today as I read it, and many of his predictions have come to pass (the dominance of web applications, the rise in popularity of niche programming languages), and most of his logic is still sound, and still insightful.

Two particular points I found interesting, and would be interesting to the Haxe community I spend most of my time in:

4. A Language Has to Be Good for Writing Throwaway Programs.

You know what a throwaway program is: something you write quickly for some limited task. I think if you looked around you’d find that a lot of big, serious programs started as throwaway programs. I would not be surprised if most programs started as throwaway programs. And so if you want to make a language that’s good for writing software in general, it has to be good for writing throwaway programs, because that is the larval stage of most software.

I think Haxe is beginning to show it’s strength here in gaming.  People are using it for Ludlam Dare (write a game in a single weekend), and then later the game scales up to be a full-featured, multi-platform, often commercial game.  Haxe is good for a quick win (especially when targetting flash), but then you have the options to target so many other platforms as your vision for your game/app expands.

I’d love to see ufront get this good.  I have so many things I would like to use as an app, but which I don’t feel justify an ongoing subscription to an online company.  Many of them could get an MVP (minimal viable product) out in a weekend, if the framework was good enough.  And it’s getting good enough, but still a little way to go :)

And then this:

2. Speed Comes from Profilers.

Language designers, or at least language implementors, like to write compilers that generate fast code. But I don’t think this is what makes languages fast for users. Knuth pointed out long ago that speed only matters in a few critical bottlenecks. And anyone who’s tried it knows that you can’t guess where these bottlenecks are. Profilers are the answer.

Language designers are solving the wrong problem. Users don’t need benchmarks to run fast. What they need is a language that can show them what parts of their own programs need to be rewritten. That’s where speed comes from in practice. So maybe it would be a net win if language implementors took half the time they would have spent doing compiler optimizations and spent it writing a good profiler instead.

Nice insight.  I sometimes worry that the code I’m writing will be slow.  It’s hard to know if optimisations are worth it, especially if it may compromise code readability etc.  A better solution would be to focus on making profiling easy.  On the JS target you can easily use the browser tools to show profiling information.  Another option is to bake it into your Haxe code, something that the “massivecover” lets you do.  Wiring that support from massivecover into ufront or other frameworks, and generating pretty reports, would be a very cool way to encourage people to write fast apps.

Categories
Haxe

You cannot use @:build inside a macro : make sure that your enum is not used in macro

If you ever come across this error, it can be a bit cryptic to understand.

Here’s some sample code that produces the error:

import haxe.macro.Expr;
import haxe.macro.Context;
import neko.Lib;

class BuildInMacroTests 
{
    public static function main() {
        var s:MyModel = new MyModel();
        MyMacro.doSomething( s );
    }
}

class MyModel extends sys.db.Object // has a build macro
{
    var id:Int;
    var name:String;
}

private class MyMacro 
{
    public static macro function doSomething(output : Expr) : Expr {
        return output;
    }
}

I’m still not sure I have a full grasp on it, but here’s a few pointers:

  • It’s not necessarily an enum – it can happen with a class or interface that has a “@:build” macro also.
  • The basic sequence happens in this order:
    • BuildInMacrosTest.main() is the entry point, so the compiler starts there and starts processing.
    • When it hits “var s:MyModel”, it does a lookup of that type, realizes the class needs a build macro to run, and runs the build macro.
    • When it hits “MyMacro.doSomething()”, it types the expression, and realizes that it is a macro call.  To run the macro, it must find the macro class, load it into the macro context, and execute it.
    • It finds the macro class, it’s in this file.
    • It tries to load this module (hx file) into the macro context, so it goes through the whole process of typing it again.
    • As it’s loading it into the macro context, it hits the “MyModel” build macro again, which it can’t do at macro time, so it spews out the error.
  • The basic solutions:
    • Wrap your build macro declarations in conditionals:
      #if !macro @:build(MyMacro.build()) #end class Object { ... }
    • Wrap anything that is not a macro in conditionals:
      #if !macro 
        class BuildInMacroTests {}
        class MyModel {}
      #else
        class MyMacro {}
      #end
    • Keep your macros in seperate files:
      BuildInMacroTests.hx:
          class BuildInMacroTests {
              public static function main() {
                  var s:MyModel = new MyModel();
                  MyMacro.doSomething( s );
              }
          }
      
          class MyModel extends sys.db.Object {
              var id:Int;
              var name:String;
          }
      
      MyMacro.hx:
          import haxe.macro.Expr;
          import haxe.macro.Context;
          class MyMacro {
              public static macro function doSomething(output : Expr) : Expr {
                  return output;
              }
          }

A combination of the 1st and 3rd solutions is probably usually the cleanest.

Good luck!

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
Edtech

People are clueing on…

VentureBeat has a write up on Why Venture Capitalists can’t afford to ignore EdTech any longer. The wider world is waking up to the fact that something needs to change.

I just hope the change is for something more open.  They compare it to the changes in enterprise – where people where locked on expensive propriety software, and the escape has come in the form of cloud computing and software-as-a-service. This is more open in some ways (You don’t have to use a Windows machine any more, you could use a Mac or Linux or your phone or tablet or internet-powered-fridge), but in other ways, it’s more locked.  You have to keep paying the monthly bill, with no promise it won’t increase later.  You have to trust that the company will never go bankrupt, or never go evil.  And even if the company has open APIs or let’s you download your data, it usually is hard to migrate over to a competitor later.

I’d hate to see education locked up like that.  You can have these amazing learning resources – but they’ll stay on our servers, thank-you-very-much.  We’ll help you define all your lesson plans, but it’s on the condition that they never leave our app, so you’ll keep coming back.  We’ll help analyse the data about how all your students are learning and performing, but that data stays on our servers and we might use it for something else later, and there’s not much you can do about that.

I want to fight for the upcoming EdTech revolution to be open:

  • The school stays in control, and isn’t held ransom to their software suppliers
  • The content teachers create is theirs, and they can hold onto it, share it, and take it with them if they switch to a different software product.  They don’t have to write everything all over again because their school switched providers.
  • People see the value of creative commons – and they gladly cooperate in developing the best educational materials, rather than hoarding what they do for their own benefit.  (I think the teachers creating great material tend to be generous, it’s the business people that they work with that might not be).
  • When someone goes to the effort to create amazing content, and they want to share it, they should be able to.  For example, an e-book shouldn’t be stuck on iPad only.  It should work on phones (cheap ones included), computers, printouts (to whatever extent makes sense) and competing tablets.  And be future-proof and work on whatever the next-big-thing is.

Education is too important for it to be controlled by a small group of start-up shareholders.

Categories
Faith Personal

If you’re poor, today is a good day.

Imagine your head of state getting up to make a speech.  Our own Julia Gillard isn’t the most inspiring, so I’ll imagine Barack Obama – who at least can give a moving speech.  He gets up on the podium, pauses while the photographers and journalists snap some pictures of him, waits for a quiet to descend, and addresses the nation.

Today is a good day if you are poor – this nation is yours, and today this nation commits to looking after you.

Today is a good day if you are too poor to keep the fridge stocked – from today onwards there will be plenty of food for you and for your family.

Today is a good day if you’re one of the people who quietly goes about your work diligently, and are sick of being trampled on by people louder, richer or more powerful than you.  From today onwards, your hard work will no longer be overlooked, you’ll be recognised, rewarded and given more opportunities for great things.

Today is a good day for those who feel like they’re fighting a losing battle to remain a good person.  Today we say this country values and rewards faithfulness, generosity and a good heart, rather than those who cheat, lie and abuse to get ahead.  You protect your motives and stay true to all that is pure and good about humanity.  Your life will be rich as a result.

Today is a good day if your life has been filled with sadness and grief.  As a country, a community and a family today we recognise your suffering, and say we will be there for you, and do everything we can to give you a brighter future.

Today is a good day for those of you who aren’t always hard-lined, but show mercy and give a second chance.  This is not weakness, but a strength and grace that can turn a fellow human being’s life around.  From today onwards, we are a country that promotes mercy over strict adherence to rules and punishments.  If you’re willing to give people who hurt you a second chance, recognising their humanity, we’re willing to give you a second chance too – and this takes effect in all our policies.  Mercy begets mercy, love begets love.

Today is a good day for everyone who has stood between two fighting parties, and brought calm and understanding, peace and unity.  Because of your commitment to us, to all of us – the worldwide family of humanity – we celebrate you, honour you, and publicly say that this world is better because of you, and because of the risky stand you have taken.

Today is a good day for all of those who have been punished for doing what is right.  Those who have been arrested for peaceful demonstrations, those who have been insulted for standing up for minorities, those who have been fired or sued or sidelined for choosing to do what is right, rather than do what they’re told.  To those who do the right thing, rather than the easy thing – we see you, we acknowledge you, and change our rhetoric.  You’re not a “rebel” or “lawbreaker” or “dissident”.  You are one of the greats, one whose conviction challenges our society and grows us.  You are in good company with the great men and women of history.  As a nation, we will no longer fight you, but recognise you and reward you and support you in every way that we can.  We need more people like you.

When a leader makes a public address like this, it isn’t just more campaigning, an attempt at securing more votes or support.  A speech like this is a turning point.  It says that as a nation we acted one way, now we’re going to act another.  It’s a statement of what’s important to the new leader, what their season of leadership is going to be focused on, and what people can expect to change.  One group of people was previously neglected, now they will not be.  It gives both a change of policy (what the leadership is doing to support the neglected) and a change of culture (as a people, we are now to think differently, act differently, treat people differently).

This is my re-imaging of “The Beatitudes”, part of a sermon Jesus delivered that can be looked at as his inauguration speech.  The crowds recognised that this man was a leader, pronouncing a new Kingdom, and with thousands of people gathering to listen to him, here is what he has to say:

Blessed are the poor,
for theirs is the Kingdom of God.
Blessed are the hungry,
for they shall be filled.
Blessed are the meek,
for they shall inherit the earth.
Blessed are the pure in heart,
for they shall see God.
Blessed are those who mourn,
for they shall be comforted.
Blessed are the merciful,
for they shall be shown mercy.
Blessed are the peacemakers,
for they are the children of God.
Blessed are those who are persecuted for righteousness and justice,
for great is their reward.
(Common Prayer, adapted from texts in Matthew 5 and Luke 6)

This isn’t about an normal country or community or kingdom.  This about the Kingdom of Heaven – the group of people throughout the world who recognise Jesus as the Son of God, and choose to live under his leadership rather than that of their geographic/economic leaders.  The people who submit to his way of doing things even over their own wants and desires.  Jesus is their leader, and this is his inauguration speech.

Part of it is encouragement – what he, as God and as King, is going to do for them.  Part of it is direction – how we, as his people, should change our attitudes, thought patterns, behaviours and processes to adapt to this new form of government, of kingdom.

And the vision laid out is still as confronting, appealing and diametrically opposed to it’s surrounding culture, as it was when Jesus first announced it on the hills of Palestine two thousand years ago.

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.