CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Kyle Baley - The Coding Hillbilly

"We are stuck with technology when what we really want is just stuff that works" -- Douglas Adams

June 2008 - Posts

  • It's okay to show a *little* confidence

    Technically, I said I'd get technical. But there has been a spate of negativity lately and it's making my rose-coloured glasses tingle. Typically, this causes me to shut down for a little while until it blows over but I'm going to try to spread a little optimism this time instead.

    The word "no" has been bandied about for the last week or so. Specifically, "no confidence". And regarding that particular debate, I'm steering clear because I can't make an informed opinion either way. (I have a strong inclination but it's based on what others I respect have said rather than my own investigation.)

    I don't want to detract from the efforts of those involved because, like I said, I can't make an informed opinion. I just don't like seeing all the pessimistic fallout on both sides. Accusations of negligence, foolishness, ignorance, and community disservice makes me feel awkward.

    I'll admit freely that I'm an optimist. Disproportionately so. Some (including my wife) call it naivete at times. I'm more than happy to assume that the person I'm talking to has my best interests at heart in the absence of evidence to the contrary. And even with evidence, it has to be more than circumstantial.

    I admit all of this freely. But here's the thing: historically, this works for me. Luck, karma, faith, give whatever name to it your religion prefers, generally speaking, I like the results I get from assuming the best. For all the times I got walked upon, there have been a hillbilly family tree's worth of instances where I've come out ahead.

    So that's why I feel all icky when I catch myself reading about hypocrites and backlashes when I know I should just skip over to the next item in my RSS reader. It makes me wonder what went wrong that led to this point.

    Now, I'm glad their are people out their who are passionate enough to put themselves out there for their beliefs. And I'm glad people are willing to listen and provide some balance to the debate. I'm even glad for those that prefer to argue with rhetoric rather than facts. I'm not really any of these people (except maybe the last one - it's more entertaining). Call it a character flaw if you like. All I know is, I'm having a blast doing what I do.

    And that's pretty much the only point I want to make in this post, I guess. That it's okay to look around once in a while and say, "y'know, for all its flaws, this industry kinda rocks". About a dozen years ago, I abandoned what would likely be a decent career as an actuary to become a software developer because, hey, it looked like fun. And twelve years on, despite these little bumps, I can honestly say, it has been, still is, and shows every sign of continuing to be.

    So I'm making a vote of confidence. Not for any side in the debate whose specifics I've so pointedly avoided mentioning. But that it will be resolved in a satisfactory manner, for both sides as well as for the industry as a whole.

    And if it doesn't, what's the worst that could happen?

    Kyle the Rhetorical

    p.s. I reserve the right to reverse my position if I ever get audited.

    Posted Jun 27 2008, 11:47 PM by Kyle Baley with 9 comment(s)
    Filed under:
  • BahaNET meeting and .NET Rocks

    I've become rather acutely aware that my content has been lacking of late in the technical department. But I do have a couple of community announcements to make that are time-based so I'll compromise a bit and combine them into a single post. Then I'll take a hiatus until I have something more generically useful to say.

    First off: Next BahaNET meeting is tonight at the usual digs, IPBS House. And based on past experience: When I say Moseley Lane is right after the entrance/exit to Harbour Bay off Shirley Street, I mean it's RIGHT after. As in about three feet. You can basically make a U-turn from the Harbour Bay exit on to Moseley Lane. Don't miss it.

    The topic will be: connecting a website to a database. We'll discuss basic CRUD operations and yes, we will be dragging and dropping for better or for worse. You have to know your audience. Take comfort in the fact that I'll attach a bunch of codicils as I'm presenting. Hopefully, I'll be able to demonstrate the Dynamic Data thing as well, assuming I have time to look into it.

    Next announcement: Donald Belcham and I recorded an episode of .NET Rocks earlier this week and through the magic of technology, it is already available. The topic, as you may have guessed, is Brownfield development. Elapsed time 'twixt the initial e-mail and the finished product was about ten days, which is pretty amazing. Even if Carl refused my request to digitally enhance my voice so that it sounds like Humphrey Bogart. ("Of all the apps in all the contracts in all the world, she had to refactor mine.")

    And to top it all off, Derik Whittaker will be releasing the first in my series of Brownfield casts tomorrow at www.dimecasts.net. First one is on setting up your version control structure. There are many more to come and feedback is welcome.

    Kyle the Supersaturated

  • London alt.net Beers - Recap

    Many thanks to Sebastian Lambla for inviting me to the alt.net London beers this past Tuesday evening. It was a fun evening and if you are in the London area, I'd recommend checking out future meetings. This was the second night out and they have plans to run it every month in the second or third week.

    You can watch for it on the alt.net list but if, like me, you're stepping back from the list, Sebastian's blog is probably your best bet. He's a good resource to have in your blogroll in any case.

    As it was only the second one, the format is still in flux but I like what I heard. Future meetings will including a period of tech talk on a pre-determined topic followed by much socializing. And in my experience, few places on earth are as amenable to that as central London.

    Also thanks to the local community leaders, Zi Makki and Craig Murphy, as well as the eight or ten others I met briefly but didn't get to talk to as much as I would have liked. For a hillbilly working on his own in the .net frontier that is the Caribbean, it was a much-needed burst of geek socializing.

    Kyle the Consorted

  • [Rehash] Canadian Taxes for Non-Residents

    Hillbilly's not in much of a position to wax technical this week as he babysits budding economists in an oil & gas course in London. There's a story behind why I'm doing that but it's nowhere near as interesting as the one you've just made up in your head so I'll let that add to the perceived mystique that is my life. (Seriously, the Bahamas isn't *that* great.)

    In any case, I got tired of counting the number of times the instructor would say "consequently" (at last count, eighty-fi--er....eighty-six). So I went trolling through my old blog for something that was worth repeating to a larger audience. Slim pickings, let me tell you. But found one that has some uncharacteristically useful information. I've updated it with some recent experiences as well so for those that read the original, don't forget to pay for the upgrade.

    The topic is tax implications of non-residents working in Canada. It's specific to the Bahamas, which doesn't have a tax treaty with Canada. So, let's start off by coverin' my hillbilly butt.

    I. AM. NOT. A. LAWYER.

    I have never been a lawyer. I have no aspirations of being a lawyer. Until I decided to write this post, I couldn't even spell lawyer. I have taken a single course in commercial law over ten years ago which is enough to make me laugh at some of the contracts I've had to sign but that's it. Any advice implied here is based on my aimless meanderings through the Canada Revenue Agency and dealings with other people. If you follow it, that's your fault, not mine. Like I often say, "You can't save everybody."

    Here's the scenario: I am a Canadian citizen but a Bahamian resident. Often I will work in Canada for a period on a contract, then make up some excuse to go home. Then I work remotely from the Bahamas for the remainder of the contract.

    There are three areas to consider: Income tax, GST, and CPP/EI. I'll start with the one people ask most about.

    Income Tax

    Short version: Non-residents pay 15% income tax on any income earned while on Canadian soil.

    Canadian citizen/Bahamian resident/U.S. contract

    I have limited experience doing this in the U.S. If you are so inclined, it is dead simple for Canadian citizens to get a visa to work in the U.S., especially in the IT industry. Go to the airport a half hour earlier than you normally would with appropriate documentation. A surly-yet-lovable government-type agent will review your paperwork and attach a shiny new TN visa slip to your passport, valid for one year (or technically, the length of the contract if it's shorter). You can re-apply for the visa ad infinitum from what I understand but I haven't tried it myself.

    Appropriate documentation (from memory): Your resume, your passport, your birth certificate (optional), a letter from your prospective employer asking the agent for a TN visa with specific dates, a copy of the contract, and basically anything else you can think of to prove you are Canadian and going to work for someone in the US in IT. (NOTE: underwear with your name stitched on it is still a grey area. If you try it, look for a female officer.)

    Word of caution: When you leave the US for any reason while you have a TN visa, they are supposed to take the visa slip off your passport and attach a new one when you re-enter. If they don't, you *may* encounter problems when you re-enter. Your passport will have a stamp indicating that you have a visa for up to a year. You won't technically need the paperwork when you re-enter but it's a good idea to keep it with you just in case.

    That is what I've learned from both the CRA website and from a fairly respectable tax accountant firm. While you are physically in Canada taking advantage of Canadian roads, sewers, and brothels, you must pay taxes to someone. If you can prove that you have to pay taxes to some other country, they won't tax you twice. Unfortunately, there is no tax treaty 'twixt Canada and the Bahamas, likely because there is no income tax in the Bahamas.

    The person that's paying you is required to withhold the 15% income tax and remit it to CRA on your behalf. At the end of the year, they need to give you either a regular T4 slip or a T4-NR slip, depending on who you ask. My vote is for the T4-NR.

    Grey areas:

    Can I deduct expenses to reduce my tax?
    Maybe. My opinion is that you'll make less waves if you keep it simple. Unless you're going to be in Canada a long time (in which case, you will be a resident anyway), any "deductions" you think you might be able to claim won't be worth the aggravation. Plus then you'd need to file a return. Which brings me to...

    Do I need to file an income tax statement?
    Not sure. Have received conflicting opinions on this. If you think you should be paying more or less than 15%, then yes, you definitely do. Otherwise, I've had at least one CRA person claim you need to fill out a regular income tax form just as if you were a Canadian resident. Everyone else says you don't need to bother. Having said that, the fact that you get a T4 slip at the end of the year suggests otherwise... ** UPDATE ** I'm almost positive you're supposed to file a non-resident return. It should be pretty straight-forward since you've paid exactly what you are supposed to. But I've never done it.

    What if you come back to Canada and work for a short period during the contract?
    Use your judgement. When I come back for a few days or a week, I don't generally notify the contracting agency. If I'm back for the summer, it's reasonable to assume I'm hunkering down for a while and should pay the government their due.

    GST

    GST is handled completely separately than income tax, despite the fact that you call the same number to ask questions. There are different rules regarding residency status for GST. Meaning you may be a non-resident for income tax purposes but a resident for GST purposes. And residents need to collect and remit GST.

    The rules here are a little easier to follow. If you expect to make more than CDN$30,000 in a given year while in Canada, then you need to charge GST. For most consultants, that's 'twixt two and four months worth of work so chances are, you'll need to file.

    To collect GST, you need a Business Number which is easy enough to get. Call up CRA at 1.800.959.5525 and they should be able to give it to you over the phone. Here is the gist of what to tell them:

    • I am not a Canadian resident but I *am* a Canadian citizen. I will be working in Canada for a period of X months and expect to make over $30,000 during that time. I'd like to apply for a Business Number for GST for the period that I am in Canada.
    • I will file GST annually
    • I do not need a payroll account
    • I am a sole proprietor

    They may try to tell you that you need to call the International Tax Office but that's wrong. The International Tax Office doesn't deal with GST at all.

    Grey areas:

    Should I keep my Business Number active after I leave the country?
    Probably not. In my experience, it's pretty easy to deactivate and reactivate it so it's worth the phone call to deactivate it when you leave. And that's all you need to do. There's no paperwork involved. And you do *not* charge GST for any work you perform outside Canada.

    Should I incorporate?
    My opinion is no, you shouldn't. The major advantage of incorporation is to lower your taxes which isn't really an issue for non-residents. More importantly, with you as the major shareholder, it constitutes a major residential tie to Canada, something you should avoid.

    ** UPDATE ** Setting up a corporation in Canada means the corporation will pay tax in Canada. In my experience, *EVERY* contracting agency will try to pressure you to incorporate. Fair enough, they don't want to rock the boat any more than you do and dealing with a foreign entity is a warning flag. But stick to your guns. I had to go through three agencies in my last contract before I found one that would accept me. And even then, I had to sub-subcontract.

    CPP/EI

    I normally wouldn't add this section but recent adventures warrant mentioning. Until then, I would have said you don't need to pay CPP or EI, nor does the company who pays you. This is based on conversations with both CRA and a fairly confident-sounding international tax accountant. As a non-resident, you aren't entitled to EI so it makes sense that you shouldn't have to pay it. CPP is more of a grey area but by most accounts, you shouldn't need to pay into that either.

    The sole dissenting voice in this is the contracting agency I currently go through who is rather insistent that they have to charge me for it as well as pay their share. They claim that there are different rules for contracting agencies which could be the case but I suspect they just want to cover their asses and not do anything that may trigger an audit. In any case, I've sent numerous e-mails quoting international tax accountants and linking to relevant CRA sites, all of which have gone ignored. So I'm letting them have their way partially because I'm in the country only for another month and partially because I think their share of the EI/CPP payments cost more than the commission they're charging me.

    No tax and kayaks, too! Which reminds me: CPP and EI are charged only while you are in the country, assuming they should be charged at all, which I doubt.

    ** UPDATE ** The contracting agency in question claims there was a miscommunication and they recanted when I pressed them.

    Residency

    Residency means different things for income tax than for GST. For GST, if you earn $30,000 while in Canada, you are a resident for GST purposes. Otherwise, you have to consider the many other scenarios on their website.

    For income tax, the rules are not nearly as concrete. If you are physically in Canada for 183 days or more (whether you work or not), you are a Canadian resident.

    There are some dire ramifications if you are considered a Canadian resident for income tax. Namely, you are taxed on your entire worldwide income for the year, regardless of where you earned it. Unless, of course, you pay tax on your external income in another country, in which case, Canada does not double-tax. But since there is no income tax in the Bahamas, this means I'd have to pay tax on my total income for the year. And given the cost of living, it's something I like to avoid.

    Even if you are in the country less than 183 days, you still may be considered a Canadian resident. And this is where it gets iffy. There is nothing that says, "If you meet this set of criteria, you are a Canadian resident". Rather, CRA will look at a combination of factors and essentially make a judgement call. Some of the questions they'll consider:

    • Do you own a home in Canada?
    • Do you have a registered vehicle in Canada?
    • Do you have bank accounts and credit cards in Canada?
    • Do you have family and other personal ties to Canada?
    • Do your spouse and/or children live in Canada?

    Answering yes to any of these questions is a mark against you but again, it doesn't mean you're a resident. For example, maybe you own a home but rent it out. Then it becomes more of an investment than a residential tie.

    All in all, it's kind of wishy-washy so the more you can do to wedge yourself into the country to which you're moving, the better. Get a local driver's license. Buy property. Enroll your children in local schools. Get credit cards. Attend a local gay pride parade. That sort of thing.

    Final note on residency: when you leave Canada, I believe there is a formal process to follow to claim you are no longer a resident. I haven't followed it. I just left and stopped paying taxes (which was easy to do because I didn't earn money in Canada for the first two years after I left). You could do the same thing but the underlying theme I'm picking up from my dealings with CRA is that they are fairly practical, at least in the tax department. As long as you act in a relatively reasonable manner, they should leave you alone.

    More information

    Seriously, the Canadian Revenue Agency website is really good at publishing pretty much anything you need to know about Canadian taxes. Not only do they have the actual laws, but there is a virtual cornucopia of questions and answers covering most scenarios, all in relatively plain, if not quite Queen's, English. And pretty much all forms are available in fillable and printable formats. You shouldn't need to fill any of them out but they're a good reference for when you call CRA so you can expect which questions they'll ask.

    The main phone number for CRA is 1.800.959.5525. As a call centre, they are better than Expedia but worse than Go Daddy (who, admittedly, gets a few bonus points for having the best on-hold music ever). For the most part, you aren't on hold *too* long and the agents are friendly and seem knowledgeable enough even if they give conflicting advice.

    Specific sections:

    Note that it's still hard to get concrete answers to some questions, even if you call them up but this is still the best resource I've found short of paying someone a lot of money for advice. And speaking of paid advice, if you are serious about this scenario, you should seek it out. After you've gleaned all you can from the CRA website. I used KPMG in Calgary and am reasonably happy with the advice I got, if not the price I was charged (** UPDATE ** or the follow-up service I got). I also talked with someone at Continental Tax and I wish I remembered his name because he was amazing. Gave me a ton of free advice over the phone and I will not hesitate to engage their services in the future.

    Summary

    The overriding rule when negotiating the Canadian tax system is the same is it is in software development: Favour maintainability over all else. That means: don't rock the boat. Get into the country, pay what's owed, and leave. If you want to minimize the amount of tax you pay as a non-resident, the best way to do it is to minimize the amount of time you're physically in Canada, not by nickel and diming your way through "expenses". If you start looking for shortcuts, you're more likely to be audited. And worse yet, if you *do* get audited, you're then in a worse position to defend yourself.

    In my opinion, the Canadian tax system is based on fairness (with respect to eligibility, not necessarily the percentage you have to pay). If you're in Canada, you pay tax to the Canadian government. If not, you don't. If you act according to this, you should be okay.

    But just in case, it's best not to leave a forwarding address.

    Kyle the Deductible

    *EDIT: October 17, 2007*

    After clearing up some communication issues, the contracting agency consulted their own accountants and has confirmed
    my position. If you are *not* a Canadian resident, you do not pay EI, CPP, or income tax while you are working outside Canada. Ditto for collecting GST. This applies only if you are regularly based outside Canada so don't be plannin' any extended business trips to the Caribbean expectin' your tax savings to cover your bar tab.

  • Be it ever so humble...

    The obligatory follow-up post to the 99% of you (give or take 2%) that didn't attend my presentation, to let you know that I gave a presentation. This one is pure entertainment value only so if you're looking to code better, maybe Greg Young or Matt Podwysocki will finally post something technical.

    I talked about Brownfield application development at the Florida Tweener weekend. On a side note to Joe Healy: Florida 'Twixter sounds a lot cooler. It's because of the 'x' (Come to think of it: Florida 'Twixxxter would be even better...). Nevertheless, he pulled off a pretty cool event in record time. At least from the brief bit I saw. I talked for an hour from 8:30am until 9:30am, then bolted like a cockroach (not the Bahamian kind, they're a little more lackadaisical when the lights come on).

    Reason for my leaving was that I had left my family alone with a credit card in the middle of theme park central. So the rest of the day was spent at Universal Studios Orlando and its sister park, Islands of Adventure, with them. My entertainment gland was supersaturated by the end of the day. Tip: when you're going for a single day, the Express Plus passes are just about the best money you can spend there. Seriously, bring a bag of peanuts and use the food money for these incredible time-savers. By my estimate, we saved no less than three hours of line-waiting during the course of the day. Longest line was RipSaw Falls for thirty minutes. All others were less than five.

    The trip home was a noble little disaster. Delayed leaving Tampa, which meant getting bumped to a later connecting flight in Miami. (Little known fact: Miami's airport code, MIA, is actually a double-entendre. I'll let you figure out the other meaning. Hint: it has to do with luggage.) This usually isn't a problem because there are anywhere between two and forty-seven flights from MIA to Nassau on any given day, depending on the blood alcohol level of the American Eagle pilots.

    Today, however, all twelve remaining flights (must have been a heckuva bender last night) were oversold. And it took a couple of batted eyelashes and an eight-year-old's temper tantrum* to get us on a flight out of Fort Lauderdale the next morning on an oversold flight. All due credit to American Airlines' customer service people. They may not be competent as a rule, but they were unflappably nice in the face of a customer service disaster that, by the time we got there, looked like it had started during the Clinton administration.

    Once flight confirmation was achieved, we set out to find a hotel in Fort Lauderdale. This may sound like an easy task unless you are intimately familiar with the wireless internet access in MIA, which does not recognize the Bahamas as a country for credit card processing. Nor, in fact, does it recognize the internet at all. Luckily, Mrs. Billy has a travel agent on speed dial...

    The cab ride to the hotel in FLL was the highlight of the day. The driver was Kurdish and if you *really* want to hear about a "tweener weekend", listen to his stories about living 'tween Iran and Iraq for half his life.

    Rest of the trip was uneventful which, ironically, makes it the best part of the flight home.

    Back to the presentation. It went pretty well, I think. Started out with three early risers but ended around twenty-five strong. For me personally, it was another case of wondering why I go through the expense as I walked to the venue and wondering why I don't do this every weekend as I walked back to the hotel afterward. It really is fun though I still need to work on my audience participation skills.

    The show, unfortunately, was not taped as I copied the slides over to one of the TechEd computers and barely had enough time to get the projector working. As it is, I was mike-less throughout and I'm not exactly Rush Limbaugh when it comes to voice projection.

    Next up on the North American tour will be a couple of talks in the home turf. One in Calgary and the other in Edmonton. Both at the end of July and that's about as detailed as it gets so far. The Calgary site lists me as presenting on ASP.NET MVC which is good to know. Gives me a place to start anyway...

    Kyle the Homebound

    *Bonus trivia: I performed one of these acts myself. You may be surprised at which one. And at the level of success I achieved

  • SimpleStateMachine on CodePlex

    I bet you didn't know hillbillies believe in kismet. Well, we do, mostly because it typically works in our favour. The minute things start going wrong, well, that's just plain someone else's fault and typically requires at least one lawsuit.

    But today, kismet. That's the only reason I can think of why someone would post a SimpleStateMachine project on CodePlex not three days after I started working on this very problem.

    <-- snip -->

    I've just cut out an Imperial tonne of back story that upon re-reading was boring as all git out, though wittily told. I'm going to skip to the implementation.

    Which still requires some knowledge of the worfklow I'm trying to implement.

    image

    This image encapsulates quite a few false starts, most notably in the places where it "branches" off (the beige boxes). My first implementation was a flow where a job could be in three states at once. For example, a job could be "To Be Invoiced", "Awaiting Hydro Approval" and "Awaiting Regulatory Approval" all at the same time. Not a traditional definition of a State Machine but one that I could start coding against nonetheless.

    Then comes the SimpleStateMachine that was oh so enticing but also a little less liberal with the rules of a state machine. So I moved, after much deliberation, to the above diagram in which the branches represent the launching of separate workflows. Thus, in a sense, a job *can* be in more than one state at once, but not in a given workflow. Now I could try out the SimpleStateMachine and still appeal to my sense of ancestral ambiguity.

    The code is surprisingly easy to follow, not least of which is because of the unit tests and demo application, both of which paint a pretty good picture of how the application can be used. When you need to step through it, you'll find things clearly separated out so it's pretty easy to figure out what's going on.

    I'm including the entirety of my main workflow below partially because I like testing out the scrollbars of your RSS reader but mostly so you can see how simple it is. I'm told it's in Boo format but it's my first exposure to the language so I haven't verified. All I know is that it works.

    workflow "Basic Job"
    
    state_identifier_target @JobStatus
    event_identifier_target @JobEvent
    
    on_enter_state      @PersistState, "on_enter_state"
    
    _event @SetUp
    _event @DraftingCompleted
    _event @DraftingRejected
    _event @DraftingApproved
    _event @Invoiced
    _event @Paid
    _event @Uncollected
    _event @Cancel
    
    state @Ordered:
      when @SetUp                >> @InDrafting
      when @Cancel               >> @Cancelled
    	
    state @InDrafting:
      when @DraftingCompleted     >> @ToBeChecked
      when @Cancel                >> @Cancelled
    
    state @ToBeChecked:
      when @DraftingRejected      >> @InDrafting
      when @DraftingApproved      >> @ToBeInvoiced
      when @Cancel                >> @Cancelled
    	
    state @ToBeInvoiced:
      when @Invoiced              >> @AwaitingPayment
      when @Cancel                >> @Cancelled
    	
    state @AwaitingPayment:
      when @Paid                  >> @Closed
      when @Uncollected           >> @BadDebt
    
    state @Closed
    
    state @BadDebt
    
    state @Cancelled

    This is *almost* something I could assign to a business user to create. Not that I would. But they could certainly read it and figure it out with minimal coaching.

    You'll notice the on_enter_state task at the top. This means that the PersistState task (which is a custom task I've written to write the job status to the database) will execute each time we enter a state.

    This concept also applies to individual states. For example, this workflow doesn't totally match the diagram. I've omitted the part where it launches two other workflows. The way I plan to implement them is to modify the @ToBeInvoiced task as follows:

    state @ToBeInvoiced:
      when @Invoiced              >> @AwaitingPayment
      when @Cancel                >> @Cancelled
      on_enter_state @LaunchHydroWorkflow, "on_enter_state(ToBeInvoiced)"
      on_enter_state @LaunchApprovalWorkflow, "on_enter_state(ToBeInvoiced)"

    That is, I will create custom tasks to launch the two other workflows after we enter the ToBeInvoiced state.

    So check out the library if you are working with workflows (and props to Ayende for pointing me to the library to begin with). As an added bonus, the author is amazingly quick in responding to issues. In the time it took me to type this up, he added the ability to use an IoC container with your custom tasks and a more efficient way of searching for custom tasks. Both in response to questions I asked on the discussion list.

    Next post will likely be on the actual implementation of this workflow. Suffice it to say that the project lives up to the premise on the home page:

    "The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications."

    Kyle the Flowed

More Posts

Our Sponsors

Free Tech Publications