I am Joshua Poehls. Say hello Archives (not so) silent thoughts

First Steps in Go: A Scoreboard App

Mostly I just read about new programming languages. Call it a hobby. Only once in awhile am I struck with enough interest to want to try something out on a real project. Go is the most recent of such interests. As someone who loves a lot about Node.js, I’m looking forward to seeing how Go compares and whether it solves my Node and JavaScript pain points.

Scores is my first app in Go. It is a very simple scoreboard app for “tracking personal records between friends”. You define a record like “max push-ups” and you create a scoreboard for it. The scoreboard is specific to your group of friends or “team”.

You try out a test scoreboard or dive in and create your own board.

Screenshot of test scoreboard

Anyone with the URL of your scoreboard can post scores. Only the top 10 scores are kept. Obviously it is wide open to trolls so you probably won’t want to share your scoreboard URL publicly.

Screenshot of scores homepage

I think this is a pretty fun and useful app and I’d love to know what you think! Please take it for a run, invite your friends to compete with you for a high score.

Screenshot of empty scoreboard

If it gains some interest then my plan is to keep this running and improve the code overtime as I learn more Go. Honestly, the improvement part will probably happen regardless. The primary goal of this project is to try out Go in a real app and I’ve already got a laundry list of things to improve.

I encourage you to read the source and comment. Please, do not take this as a great example of idiomatic Go code. This is a work in process from someone learning the language. Take it as such.

Why Go?

You may be curious about what attracted me to Go. It is a very simple language. In a way, it was designed to have a lack of features rather than an abundance. While many languages take the stance that giving the developer more ways to do something makes their job easier, Go says this is wrong. Less is more. More features introduce disparate coding styles and make it difficult to maintain consistency. You can look at 2 or 10 different projects in some languages and feel, largely, like you are reading 2 or 10 different languages simple due to style changes or which features of the language the APIs are designed around.

In short, Go was designed to make developer’s quality of life better. Clearer code, faster builds, great tooling.

I’m a sucker for simplicity and I’m a big sucker for great tooling. Developer tooling is a passion of mine and Go has made this a top priority. Built-in memory and CPU profiler, deadlock and race detection, documentation generator that supports executable example code, built-in testing and benchmarking, a Go language parser and lexer in the standard library; these things excite me.

I’m not going to elaborate more on Go because, honestly, I’m a total noob. I’ve been following the project for awhile but only started writing code recently and am just now working on an actual app. Thus, my opinions on the language and its benefits over the long-haul are very weak. Try it for yourself and make your own opinions.

If this sounds interesting to you then I encourage you to watch a couple of videos to get a feel for the philosophy and tooling of Go.

So, what do you think of Go? Let me know! And don’t forget to create a scoreboard and let me know what you think of that as well!

⦿

Does your business need a website?

A friend got me thinking about this today. Does a business' website design matter? Does a business even need a website?

The answer strongly depends on the type of business we are talking about. If the business offers digital services of any kind, then obviously they need a website and their design is going to play a huge role in their success. The real interesting discussion begins when we talk about brick and mortar businesses that don't offer any digital services.

Let's talk about those brick and mortar businesses. Let's assume a few motivations for them wanting an online presence.

  • The Yellow Pages are dead; people find businesses by looking online.
  • Provide customers a way to contact them with questions or feedback.
  • Provide information about their business and services, including:
    • Hours of operation
    • Location and phone number, with directions
    • A menu (for restaurants)
    • General description of services
    • Photos of their work or their business

The first instinct might be to create a website for the business that provides this information. That might not be the best course of action, though. Think about this - how will prospective customers be looking for your business? Sure, googling for local services is definitely a thing and could result in your website being found. However, that isn't the best way to surface yourself as a local business in searches.

Also, website design is hard. Let's not confuse the subject, making a website is dead easy. Anyone can do it. Making a website that is aesthetically well designed, surfaces information in an intuitive way, is compatible with and responsive to the myriad of devices on the market (phones, tablets, laptops, touch screens, etc), is optimized for SEO, accessibility for impaired users, integrates well with social services using things like Open Graph protocol - this is hard. These are all things that are involved in designing a modern website that represents your business well and is accessible to your potential customers. Creating this kind of online presence is non-trivial.

Sure, you can find templates that will help with a lot of this, but no template can write your copy, take quality photos, digitize your logo, etc. And many templates need tweaking to ensure the SEO, accessibility, and social integrations work and work well. If you don't know what you are doing then the end product will look like you didn't know what you were doing in one way or another.

Not all businesses need a robust modern website, though. As much as it hurts me to admit that. However, all businesses should understand what such a website is and what it involves. They should see examples. They should know that this is possible and a marketing tool that is available to their competitors. If it is decided that such work isn't warranted, then fair enough.

We need to dispel with the myth that websites are easy and any teenager with a keyboard can do it. They can, but the end result will reflect such. Just like any teenager with a hammer can be a carpenter. Web design is skilled technical work. There are DIY dog house kits available just like there are DIY website kits but don't confuse that with a professionally built product.

Now that it is clear that a website isn't necessarily a simple thing, let's revisit the question of whether a website is even necessary. I mentioned earlier that a website wasn't the best way to surface yourself as a local business online. There are a lot of places online for your business to market itself and Google (and other search engines) will rank you higher in results if you do.

What am I talking about? All of these sites have a way for businesses to register themselves and maintain their presence. Your business is likely already on these sites and you don't know it. They might have incorrect information or no information. You should look!

I would argue that many businesses would be best served by simply managing their presence on these sites. This is where potential customers are most likely to find you online. You can provide all of the basic information about your business including hours, location, phone number, and menus in a standard way that is intuitive to users. Your customers can provide feedback and reviews about your services that help others decide whether you are a good fit for them. These services are how your customers expect to be able to interact with your business online.

A website for a brick and mortar business is simply icing on the cake. Even if you have a website you'll want to look good on these other sites as well because that is probably the first place a potential customer will find you. When it comes to bang for the buck you can't beat leveraging all of these amazing sites that customers already use every day. Let them do the hard part of marketing your business and let you focus on making customers happy.

If you have a business and have questions or need help in this area, contact me and I'll either help you out or get you in touch with someone who can.

⦿

Initiation into mechanical keyboard geekdom

A laptop style short keyed keyboard has been my instrument of choice for years now. They are easy to type on and fast. I gave up the stock Dell keyboards years ago for a bare bones Logitech.

Old Logitech keyboard

A few months ago I started digging into mechanical keyboards. They had caught my attention and suddenly I really wanted one. I was ready for a new keyboard, as you can see my Logitech is positively filthy. Why clean it when you can buy a new one, right?

After a lot of research into the various mechanical switches and watching many YouTube videos, I finally decided. I ordered my first mechanical keyboard from, fittingly enough, MechanicalKeyboards.com.

My new Ducky DK9087 Shine 2 arrived and it was love at first press. I’m still training my fingers to the slightly different layout but this thing is amazing.

Buying this keyboard has been like buying new shoes. You stand straighter, walk taller, type faster, feel better.

New Ducky keyboard

New Ducky keyboard

A quick breakdown is in order:

  • Those funky etches you see on the keys? That’s Chinese, or rather zhuyin which is a phonetic system for transcribing Chinese. I opted for the Chinese version of the keyboard which is identical to the US version except that it adds these additional characters to the keys.
  • I got the green LEDs but they make the board with blue, white, yellow, and red as well. It was a tough decision!
  • The LEDs have 5 brightness levels ranging from humane to blinding. You can even program which keys are lit up and save them as presets.
  • All of the standard media keys are there. Play, pause, stop, volume, mute, and skip.
  • The finish is a very subtle matte. No glossy fingerprint attractor here!

New Ducky keyboard

I opted for the Cherry MX Brown switches which are a good middle ground between the Blue (more clicky) and Red (linear). They feel perfect. I also got the Tenkeyless version of the board because I never use the 10-key and wanted a super short keyboard that wouldn’t push my mouse out of the way.

New Ducky keyboard

What is the typing like? Oh, so sweet. Each press resonates and builds a rhythm in your fingers. It is like switching from organ keys to real piano keys. You feel the depth and play with new feeling. If typing is your art then you absolutely must try this quality instrument!

I went out on a limb and bought this thing without ever having tried it in person. I totally scored. If you have never considered a mechanical keyboard before then I seriously recommend you check it out. Take the plunge, go get one!

Edit

I just ran across these photos of the MechanicalKeyboards.com display room. They were taken when a GeekHack Meetup toured the facility. So cool!

⦿

Non-enumerable properties in JavaScript

It isn’t very common in the wild but JavaScript (as of ES5) does support non-enumerable properties. That is to say, objects can have properties that don’t show up when you do a for...in loop over the object or use Object.keys() to get an array of property names.

I spent way too long tonight figuring out why a property was not being included in the JSON.stringify() output because I didn’t remember that this was possible. You see, stringify() works by enumerating the object’s properties. So it makes sense that non-enumerable properties would be ignored.

Let me explain.

var person = { age: 18 };
person.name = 'Joshua';
person['color'] = 'Red';

Object.keys(person); // ['age', 'name', 'color']

That is how you typically create and assign properties. We know that they are enumerable because they show up when you call Object.keys(person).

To create a non-enumerable property we have to use Object.defineProperty(). A special method for creating properties on an object.

var person = { age: 18 };
Object.defineProperty(person, 'name', { value: 'Joshua', enumerable: false });

person.name; // 'Joshua'
Object.keys(person); // ['age']

See there? Our name property didn’t show up because it wasn’t enumerable. Consequently, doing JSON.stringify(person) would not include the name property either.

Hopefully this will help you the next time a property is missing from your stringified object and you can’t figure out why. Good luck!

Bonus!

Object.defineProperty() is also how you create read-only properties. Didn’t know you could do that in JavaScript? Time to study up!

⦿

Substack's philosophy of small things

Those of you who follow the Node.js community at all will recognize substack as one of the most prolific package authors on NPM. You have probably also picked up on the fact that he is a big fan of small packages.

I ran across this interview the other day and I think substack communicates his “small things” philosophy well. Simply put, the UNIX philosophy works. Do one thing, do it well, and it will stand the test of time.

SRP for all the things! Once you learn to break up your projects into isolated chunks, the next step is to learn how to break up your monolithic app into coordinating services. It's all the same principle, and it works well.

Paraphrased from the video.

If you want to be writing things that people will still be using in 20 years, you’ve really gotta only do one thing. If you try to do other things, somebody else will come along and do that one thing way better because they focused more. So you’re just wasting your time by writing big things because they won’t be with us in the future. It’s really wasted effort.

⦿

Google Chrome and WOFF font MIME type warnings

If you are getting warnings like Resource interpreted as Font but transferred with MIME type font/x-woff in Google Chrome then it means your web server is serving the font with the wrong MIME type.

It took awhile for the WOFF font format to get an approved MIME type so there are several variations hanging around.

  • font/x-woff
  • font/woff
  • application/x-font-woff

Thank God an official type was finally decided on, application/font-woff.

Unfortunately, Google Chrome (as of 26 beta) still expects you to use application/x-font-woff and doesn’t recognize application/font-woff as a valid MIME type. This has been fixed in the WebKit trunk but hasn’t been merged into Chrome yet. The Chromium bug report has been closed so it should be coming soon.

Until it is merged into a Chrome release you have a couple of options.

  1. You can switch to application/x-font-woff which will fix the Chrome warnings but isn’t the approved MIME type. You’ll need to change it again later.
  2. You can switch to application/font-woff which will continue to cause warnings in Chrome but is the approved MIME type. Obviously the warnings will go away once the WebKit fix has been merged into Chrome but this will take a few months to make it into a release.

Since the warnings are only annoying I would recommend switching to the approved MIME type right away. The warnings will resolve themselves in time.

IIS Express

The steps to fix this will vary by web server but for IIS Express this is how you’d do it.

  1. Open ~/Documents/IISExpress/config/applicationhost.config
  2. Search for ".woff" and you’ll find a line like this:
    <mimeMap fileExtension=".woff" mimeType="font/x-woff" />
  3. Change mimeType to application/font-woff
    <mimeMap fileExtension=".woff" mimeType="application/font-woff" />
  4. Restart your IIS Express site.
⦿

jQuery CSS Clip Animation Plugin

Yesterday I needed to animate the CSS clip property using jQuery. jQuery.animate() doesn’t support this natively so I went searching for a plugin. I found exactly what I needed in a simple plugin by Jim Palmer, unfortunately it hasn’t been updated to work with jQuery 1.8.0+.

So here you go, a forked and updated copy of the plugin which will work with jQuery 1.8.0+.

Changes include:

  • Support for jQuery 1.8.0+
  • Support for the element’s initial clip value to be specified via a stylesheet instead of an inline style
  • Support for decimal clip values (thanks to a comment by Manoel Quirino Neto)
  • Type checking fx.end to guard against errors in some scenarios
  • Support for IE8

The element you are animating must have a clip style specified. Otherwise, usage is as you would expect.

<div class="element" style="clip: rect(0px 155px 31px 0px);">
    content to be clipped
</div>
$('.element').animate({
    clip: 'rect(0px 155px 31px 146px)'
}, 500);

Refer the original plugin for a demo or to give credit to the author.

/*
* jquery.animate.clip.js
*
* jQuery css clip animation support -- Joshua Poehls
* version 0.1.4

* forked from Jim Palmer's plugin http://www.overset.com/2008/08/07/jquery-css-clip-animation-plugin/
* idea spawned from jquery.color.js by John Resig
* Released under the MIT license.
*/
(function (jQuery) {

    function getStyle(elem, name) {
        return (elem.currentStyle && elem.currentStyle[name]) || elem.style[name];
    }

    function getClip(elem) {
        var cssClip = jQuery(elem).css('clip') || '';

        if (!cssClip) {
            // Try to get the clip rect another way for IE8.
            // This is a workaround for jQuery's css('clip') returning undefined
            // when the clip is defined in an external stylesheet in IE8. -JPOEHLS
            var pieces = {
                top: getStyle(elem, 'clipTop'),
                right: getStyle(elem, 'clipRight'),
                bottom: getStyle(elem, 'clipBottom'),
                left: getStyle(elem, 'clipLeft')
            };

            if (pieces.top && pieces.right && pieces.bottom && pieces.left) {
                cssClip = 'rect(' + pieces.top + ' ' + pieces.right + ' ' + pieces.bottom + ' ' + pieces.left + ')';
            }
        }

        // Strip commas and return.
        return cssClip.replace(/,/g, ' ');
    }

    jQuery.fx.step.clip = function (fx) {
        if (fx.pos === 0) {
            var cRE = /rect\(([0-9\.]{1,})(px|em)[,]?\s+([0-9\.]{1,})(px|em)[,]?\s+([0-9\.]{1,})(px|em)[,]?\s+([0-9\.]{1,})(px|em)\)/;

            fx.start = cRE.exec(getClip(fx.elem));
            if (typeof fx.end === 'string') {
                fx.end = cRE.exec(fx.end.replace(/,/g, ' '));
            }
        }
        if (fx.start && fx.end) {
            var sarr = new Array(), earr = new Array(), spos = fx.start.length, epos = fx.end.length,
                emOffset = fx.start[ss + 1] == 'em' ? (parseInt($(fx.elem).css('fontSize')) * 1.333 * parseInt(fx.start[ss])) : 1;
            for (var ss = 1; ss < spos; ss += 2) { sarr.push(parseInt(emOffset * fx.start[ss])); }
            for (var es = 1; es < epos; es += 2) { earr.push(parseInt(emOffset * fx.end[es])); }
            fx.elem.style.clip = 'rect(' +
                parseInt((fx.pos * (earr[0] - sarr[0])) + sarr[0]) + 'px ' +
                parseInt((fx.pos * (earr[1] - sarr[1])) + sarr[1]) + 'px ' +
                parseInt((fx.pos * (earr[2] - sarr[2])) + sarr[2]) + 'px ' +
                parseInt((fx.pos * (earr[3] - sarr[3])) + sarr[3]) + 'px)';
        }
    }
})(jQuery);

Updated to 0.1.4

I updated the plugin to support IE8. This entailed adding a fallback for when $('...').css('clip') returns undefined which it does in IE8 when the clip style is defined in an external stylesheet.

⦿
⦿

Using Unix terminal shortcuts in the Windows command prompt

Unix terminals have a few basic keyboard shortcuts.

  • CTRL+L to clear the window
  • CTRL+D to close the window
  • CTRL+V to paste text

The Windows command prompt doesn’t support these by default but we can fix that with AutoHotkey.

If you don’t already have it installed, you can follow the steps in my blog post.

Add this magic to your AutoHotkey script to enable these shortcuts in the Windows command prompt and PowerShell.

#IfWinActive ahk_class ConsoleWindowClass
^L::SendInput , {Esc}cls{Enter}
^D::SendInput , {Esc}exit{Enter}
^V::SendInput , {Raw}%clipboard%
#IfWinActive

Back away from the mouse, my friends.

⦿

Using enum flags to model user roles in C#, SQL, and Go

Using an enum flags property to hold users' roles is just one trick I’ve learned from @SeiginoRaikou, one of my co-geniuses at InterWorks.

Historically I have always modeled user roles with a Role table and a many-to-many relationship with my User table.

    +-------------------+
    | User              |
    |-------------------|
    | UserId   : int    +-------------+---------------+
    | UserName : varchar|             | UserRole      |
    +-------------------+             |---------------|
                                      + UserId : int  |
    +-------------------+             + RoleId : int  |
    | Role              |             |---------------+
    |-------------------|             |
    | RoleId   : int    +-------------+
    | RoleName : varchar|
    +-------------------+

Compared to a flags enum approach this is downright wasteful. With flags, there is only ever one column to work with and it is an integer. No second table. No joins or second query.

    +--------------------+
    | User               |
    |--------------------|
    | UserId   : int     |
    | UserName : varchar |
    | Roles    : int     |
    +--------------------+

Modeling this in C# is easy.

[Flags] // Values must always be powers of two
enum UserRole : int {
  Employee = 1,
  Manager = 2,
  Admin = 4
}

class User {
  public UserRole Role { get; set; }
 
  public void AddRole(UserRole roleToAdd) {
    this.Role |= roleToAdd;
  }
 
  public void RemoveRole(UserRole roleToRemove) {
    this.Role &= ~roleToRemove;
  }
  
  public bool IsInRole(UserRole roleToCheck) {
    return this.Role.HasFlag(roleToCheck);
  }
}

Flag enumerations are just as accessible in SQL.

-- Add users to the Admin role
UPDATE [User] SET [Roles] = ([Roles] | 4)

-- Remove users from the Admin role
UPDATE [User] SET [Roles] = ([Roles] - ([Roles] & 4))

-- Find all users in the Admin role
SELECT * FROM [User] WHERE [Roles] & 4 <> 0

Go forth and simplify, my friends.

Update for Go

Bonus! Here is how you might model this in Go.

type User struct {
    Roles    Roles
}

type Roles uint

const (
    // Roles must be powers of two.
    RoleEmployee Roles = 1
    RoleManager        = 2
    RoleAdmin          = 4
)

func (user *User) AddRole(role Roles) {
  user.Roles |= role
}

func (user *User) RemoveRole(role Roles) {
  user.Roles &^= role
}

func (user *User) IsInRole(role Roles) bool {
  return (user.Roles & role) != 0
}

An even cleaner way would be to use iota to have Go automatically assign the flag values in powers of two. You can see this method used by Go’s own text/tabwriter package.

const (
  // Roles must be powers of two.
  RoleEmployee Roles = 1 << iota
  RoleManager
  RoleAdmin
)
⦿