Archive

Author Archive

Push Advertising Will Die

I only occasionally feel a need to write about larger subject-matter, but given the recent uptake of websites crying about my use of AdBlock Plus, I feel it necessary to add my two cents.

The current tag-oriented, push/injection advertising is dead. Not because the ads themselves are annoying (although some are), but because it has become an attack vector for Internet security threats, including ransomware. It’s also somewhat disconcerting to do a Google search on some product or type of product and for the next week get inundated with ads for the same thing. I’m pretty sure that if I search for something, I don’t need results three days later.

This led me to think about how advertising could work outside of these parameters and here’s my take.

  • Advertising will begin to be vetted for safety and accuracy. Not sure if this will happen by third parties, social-networks, or some other entity, but I think it’s an important enough task that it will happen. If I see an ad vetted by some legitimate organization, I might be inclined to click on it.
  • Advertising will become highly targeted with trackless view capability. Meaning, I can search, find, view, but no one will know what I’m looking at unless I actually click through to the product or service.
  • Rampant displays of advertising will become the thing of the past. No one wants it and we have the ability to block it.
  • High quality content websites will add pay-walls, similar to the Washington Post, New York Times, and others. We can cry about this, but I pay for the Post and will probably pony up and pay for the Times and other sites. I might even pay for SI or ESPN, but only if they change their models to offer better content, less crap, and certainly less drama.

And of course someone that comes out with a platform for trackless-view-only advertising just might make a buck.

Categories: Commentary, Uncategorized

Designing Applications in a Vacuum (don’t do it)

Throughout my career as a software engineer/consultant, I’ve run across many passionate arguments for software development methodologies. I can’t count the times I’ve been in a room with very loud discussions about placing business logic in code or in stored procedures. I think it’s safe to say that the coders won this argument and I don’t hear these discussions anymore.

There have been others….Java vs. .NET, Fat Client vs. Web, SQL Server vs. MySQL, OO vs. Procedural and so on.

There is one I’ve hear recently that’s relatively old (10 years) that has some traction, but I don’t think it’s by any means a standard. This is Eric Evans’ Domain Driven Design philosophy (there’s a book on it). Admittedly, I’ve built many systems starting from the data model and more recently looked at API First. I’ve often developer object models and domain models as a part of my process, but I never really focused on that aspect as a required first step.

With the prevalence of web applications and specifically REST, Web API, and AJAX oriented implementations, I think I’ve come to a working conclusion. None of these are starting points (API, Domain, Data). They are deliverables.

You may work between each of these deliverables as you design an application, but you will learn something different and come up with different questions when you touch each area of design.

When you touch the domain, you’ll be asking resource and behavior questions. When you touch the API, you’ll be asking extensibility and shared service questions. When you touch the data model, you’ll be asking questions about reporting, atomic transactions, and performance.

These are all very important questions and by starting at a single point, you could potentially ignore important questions and thus, important design decisions.

Windows 8 Tablet

After recently seeing my iPad break (again) from the lightest little ding to a corner, I’d had enough. As stated in my previous post, I love the iPad from a functionality perspective, but its hardware is far too brittle for my uses. I have five kids and between their game play and my work as a consultant, the iPad was bounced around too much to withstand the beating. Yes, I had a case on it during the last breakage, but the corner got dinged, which misaligned the button and power connection and I’m not spending another $100 on that thing.

So in looking at other tablets, I decided I wanted to move to Windows 8, which I’ve been happily running on my three year old laptop. The Surface RT is out because if I’m going to a Win8 tablet, I want the full OS. I’m not sure if Windows RT will survive, but it was probably important for MS to at least figure out ARM and its possibilities. The Surface Pro is a nice piece of hardware, but there are flaws. The battery life alone knocks it out of contention. If I’m going to buy a tablet, I expect better battery life than a standard laptop.

I ended up purchasing the Samsung ATIV Smart PC Pro 700T. I think there’s a new name for it now and that’s probably a good thing. Samsung really needs to get a better naming strategy. They’re far too verbose for consumer products.

The ATIV 700T comes with a dockable keyboard and unlike nearly any other Win8 convertible offering, the keyboard is pretty solid. It’s not as nice as a mac keyboard, but it’s better than either of the attachable keyboards that come with the Surface and it’s better than any of the crappy iPad keyboards you can purchase.

I’ve had this machine for two weeks and my usage varies in several ways. On the train I will undock and use it to watch Netflix or to do design work. Using OneNote and the stylus is really amazing. I can draw out my website and mobile application thoughts far more easily than with any other tool combination. There’s nothing close to this capability on either Android or iOS.

Image

No, I’m not by nature a designer. These are just thoughts for an idea I’ve been tinkering with lately. I’d hire a real designer to make it truly workable. But as you can see, being able to just rip through ideas with a stylus in OneNote is great. There’s an eraser that you can change to act like a normal pencil eraser or you can erase strokes, which is really convenient. OneNote is one of the best tablet applications you could ever use. I’ve started using it for meetings at work and will probably adopt it as a normal practice going forward.

Watching Netflix on the wide 10″ screen is significantly better than an iPad. You wouldn’t notice it if you stuck to the iPad, but having switched, viewing shows and movies is more like watching things on a big screen TV.

When I have the tablet docked in the keyboard (as I have it right now), it’s just like having a netbook computer. The main difference is that I’m running Windows 8 Pro and I’m still getting nearly 8 hours of battery life.

After finishing up this blog entry I plan to write some code and since I have Visual Studio 2012 installed, that’s just a matter of switching applications.

If you’re thinking of picking up a tablet or convertible, I highly recommend the Samsung ATIV Smart PC Pro 700T or whatever they renamed it.

The Hidden Problem with Apple Mobile Devices

So you just unwrapped your shiny new iPad or iPhone or you bought one for your kids and see the gleam in their eye. You feel warm and fuzzy about this amazing new technology. You can download all sorts of useful applications as well as highly entertaining games. The graphics are gorgeous and the usability is probably higher than on any other platform.

Then you bang it against something, knock it off a chair or table, drop it when getting in or out of your car, or one of the many other ways a mobile device can take an unintended trajectory.

The corner smashes, the glass cracks, the power connector stops working, the power button stops working, the touch capability is messed up, or some combination of these things happens.

If you have a warranty from Apple or Best Buy or some other store, you take it in and get it repaired or a replacement. However there is a limit to the number of times you can do that and if you didn’t get the extra warranty, you’re on your own.

So you can take it to a great repair place like http://www.ubreakifix.com/ and for anywhere from $100 to $200, you can get your iPad or iPhone repaired.

All of these things are true, but they entirely hide a little-known or little-advertised aspect of owning these devices. They break. They break easily. They break often.

People have spent over $6 billion dollars on repairing their iPhones. I’m sure the cost of repairing iPads is also high.

The simple reality is that these devices, although beautiful, are cheaply made and break easily. It’s expensive to repair or even warranty these devices, making for a very expensive purchase.

You’d be significantly better off with a laptop or a net book.

Categories: Commentary, mobile Tags: , , , ,

Windows 8 is Great – Don’t Listen to the Naysayers

I have a two year old ASUS K52 laptop with an I3 processor. I’m also a developer and two years is about all I can ever get out of a Windows installation before it begins to severely degrade from misuse. I install and evaluate software on a daily basis, so the OS just gets mucked up over time. Normally, I would just re-install Windows on a clean drive and move all my stuff over, but this time I took a slightly different approach.

First, I took the leap to the cloud. I moved all of my documents to SkyDrive and a handful of close-at-hand documents to Dropbox. I used SkyDrive for the larger set of documents because it’s less expensive than any of the other services out there (at a glance). I also trust Microsoft not to go out of business. Of course I made sure that anything that might be construed as a copyright violation is not in that content. I will backup kids DVD’s after buying them and make ISO’s for later use…kids tend to destroy DVD’s quickly. I’ve heard people’s accounts getting shut down for having ISO’s in their accounts. I have not moved my MP3’s up yet and I have to evaluate what the rules are before I do that. I do not plan to move my pictures into the cloud outside of a very small subset of private PicasaWeb albums. I have digital family photos from 2000 forward. Some of them are of the toddler in the bubble bath type. I know they’re just my kids being silly, but they could get flagged. Why test that nightmare? I moved my pictures to a wifi-enabled external drive. They’re there when I need them and they don’t take up working disk space.

So now that my non-OS files are safely backed up either in the cloud or on external drives, I swapped out the drive (I never erase a disk…too paranoid that I forgot something) for a brand new Intel 180GB SSD. I then proceeded to install Windows 8. It took exactly 17 minutes to install. I have no comparison to a standard drive, but 17 minutes is pretty damn fast.

I installed Offfice 13, VS.NET 2010 and 2012, Dropbox, Skydrive, and a few other programs I need on a daily basis. I quickly organized the Metro (sorry – like the Sears Tower, it will always be Metro to me) interface with Main, Office, Dev, Util, and Misc.

So this is my first review of Windows 8. I had not played with the beta and pre-release software at all. I’d seen it, but that was about it.

I have to say I think all the critics are narrrow-minded pansies. Change is often a challenge, but if you actually use the system for a few days, it becomes very natural to know where to find things. The Metro UI is just a big menu and frankly a much faster menu than the Start Menu ever was. I can throw my mouse into the lower left corner, click, find an app, click and I’m where I need to be much more quickly than using a start menu. Now, I did make extensive use of the toolbar in Windows 7, but that option is still available on the desktop.

The one thing you will love about Windows 8 is that it is smoking fast. Maybe that’s partially the SSD, but it’s so fast you’ll freak. A sleep to awake is under 5 seconds. Reboot in 15 seconds. Opening up the laptop from sleep shows the start screen nearly instantly.

The other thing you’ll love is that everything just works. I have had absolutely zero installation or support issues, and this is on a two year old laptop without any touch capability. It took me a few days to learn the ropes, but once I figured out everything, it’s all smooth sailing.

Don’t believe the naysayers when they talk about horrible user experience. It’s different, there’s no doubt about that. But it’s highly usable and very fast.

Corporate Technical Architecture and the Missing Link

I’ve had an obsession with technical architecture from the moment I started typing on a computer terminal back in the late 70’s. Over the course of my 27 year professional career I’ve had many opportunities to be involved in architectural discussions. In recent years I have led these discussions or been a part of the leadership.

I shouldn’t say discussion because my viewpoint almost always garners derision and fuels heated battles over the makeup and purpose of a new technical architecture. I’ve thought long and hard about the things I value in a new architecture over what other (most) architects value. I’ve struggled to articulate my vision and because I’m not as strong technically as others, I generally lose battles quickly and badly.

But I do know what I’m talking about and the other architects keep proving me right. Here’s why…

Almost every architecture team focuses on technical vision and business requirements. So if a company needs to be able to share services across a number of silo’d departments or divisions, this will require a certain type of disconnected and service-oriented architecture. At a high level, this is good and right. But everything goes haywire in the implementation because these same technologists decide to find the most technically elegant solution available.

What most architects fail to take into consideration, or simply deride any attempt to “dumb-down” their goals, is that the results of their work have an associated future-cost and could potentially damage the business. This future-cost/business risk is defined by the level of talent required to implement and maintain the proposed architecture.

The missing piece is the HR department and the market for available technical talent. When implementing a new technical architecture, the architecture team should be forced to sit down with HR personnel and look at current and projected levels of talent in the marketplace and their associated costs. If a proposed implementation requires senior level talent, then HR should be able to offer insight into current and future costs associated with that proposed implementation from a building and maintenance perspective.

“This year, the proposed implementation will cost the company $2,000,000. Maintenance costs will increase to $4,000,000 because the level of talent required to maintain the proposed architecture will likely come from the contractor world and not from full-time employees. We propose you lower the complexity of the implementation so that a mid-level developer can maintain the system. This will open availability and lower future costs to $2,500.000.”

This is the sort of conversation that is missing from every architecture discussion and needs to change. I’ve sort of realized that if I were to carve out a position in a firm, this is where I would excel. I would be able to work between HR and the technical team to monitor proposed implementations and their future costs and complexity.

It’s about time this position become standard in all mid to large corporations.

JavaScript, jQuery, and UI Frameworking

In my professional consulting career, I’ve been avoiding the UI area of software development for years, much like I tend to avoid reporting tools like Crystal Reports or Business Objects. I like poking around in the guts of systems. Everything below the surface is so much more interesting, or so I thought. Instead of working on UI layers, I tried to hire other people to do what I thought was fairly simple work. This wasn’t working. It turns out, in order to direct hired hands, you need to know what the hell you’re asking them to do. So I backed off having other people do UI work and realized I just need to strap in and learn it on my own. This includes iOS, JavaScript, jQuery, and anything else to do with building user interfaces. It turns out, there’s a lot to learn.

I’ll talk about iOS in a future blog entry, once I get comfortable with iOS, Objective C, and all the related tools. Today I’m going to talk about JavaScript and jQuery.

In a side-project called Zifmia, I’m developing a service/cloud based game engine for Interactive Fiction. I’ve been working on this in pieces for a long time. It’s morphed from WPF, to Silverlight, to Java, to iOS, and I finally realized that if I could create a service, I don’t need to port it anywhere anymore. Well, except maybe the Kindle since the Kindle doesn’t support connected services. (This makes sense. Most people use the Kindle for reading and are only concerned about connectivity when purchasing and downloading a new book or other content.) But for the web, smartphones, the iPad, iPod, and other tablets, a service/cloud engine is really the right way to go.

I start developing the service layer using RESTful web services. I used the Microsoft .NET WCF REST 4.0 template to provide the external layer for the service side functionality. This was great since WCF 4.0 REST works nearly perfectly out of the box. There’s very little “tuning” to do to make it work locally or on a server. The one major issue I had was with cross-domain ajax calls, but that’s solved by adding a header on all return calls from the server. The service allows a consuming application to register a user, login, start a session (game), send commands to a session, and various other management tasks. I plan to implement oAuth so that the service can be embedded in Facebook properly.

I then start playing with various platforms to consume the service. I played round with Windows Phone 7 (Silverlight) and that was drop dead simple. It takes an object definition and two lines of code to consume the service. I didn’t implement a full Application, but it helped work through some of the service prototyping issues.

I played around with iOS, but stalled out because I wanted the web interface completed first. I had a very committed developer working on it, but our communication wasn’t working well, and so I set that relationship aside for the time being. (I haven’t forgotten about you Dan…hope to catch up soon). I then started to work on the client side JavaScript code and realized there was a LOT of work that needed to be done before anyone could use Zifmia properly. The result of that work is the essence of this article.

I started developing the interfaces in jQuery and JavaScript, but soon realized the code (HTML, CSS, JavaScript, jQuery) was becoming quite convoluted and unreadable. I also realized it would only get worse if I continued. So I started asking around and researching how JavaScript/jQuery based client user interfaces should be organized. The surprising answer is that although there are a handful of serious solutions, there isn’t a lot of open thinking about how this should be done. The people that understand the need and have the ability to work through the problems have created tools, but haven’t really shared the process with the public. It’s a shame, since that’s the really important part to share, not just the code.

I looked at a few of these tools (like JavascriptMVC, Backbone.js, SproutCore) but found all of them to have aspects I dislike. Complexity, dependencies, and high learning curves. Instead of adopting, I chose to develop my own, trying to work through the issues. Here is what I came up with. This is a very simple methodology for separation of concerns in a javascript UI framework.

The first order of business is to identify assumptions:

  • We will work on the concept of a single page interface.
  • The page will have its own class/namespace.
  • The page will have a master HTML arrangement (header, body, footer).
  • The body will be a View container.
  • Each view will be based on an HTML template separate from the main html page. The HTML template will use normal HTML, CSS, and JavaScript.
  • Each View will have its own Controller or Presenter class.
  • All AJAX calls will be contained in a single Service class. (This is arguable, since a more complex web application could have highly distinct groups of service calls. More than one Service class could be adopted).

The result is a very simple and effective way to separate code in a single page framework jQuery driven website.

Create a web page called index.html similar to the one below:

<html>
<head>
    <title>Zifmia></title>
    ....
</head>
<body onload="javascript:$MyWeb.onLoad();">
    <div id="outerPanel">
        <div id="ajaxLoading"><img src="images/loading.gif" alt="Loading" /></div>
        <div id="headerPanel"><p>Textfyre Presents, A Zifmia+Web Portal (Beta)</p></div>
        <div id="viewContainer"></div>
        <div id="footerPanel">Copyright @ 2011 Textfyre, Inc. - All Rights Reserved</div>
    </div>
</body>
</html>

In the head section of the html page, create a class and create an instance of the class as MyWeb:

var $MyWeb = new mySite();

function mySite() {

    this.controller = null;

    this.username = getCookie("username");

    this.onLoad() = function() {
        // Initialize page here.

        // based on your page logic, cookies, etc, determine the initial state of the page
        // this is where you would determine which view to show, or to show the default
        // view. Based on whatever view is needed, we set that controller to the page
        // controller and call init(), which should be a standard function on all
        // controllers.

        if (username != "") {
            this.controller = new sessionController();
        } else {
            this.controller = new defaultController();
        }

        this.controller.init();
    };

}

Since I assume you have a design in mind, you should be able to separate the various views on your own into html templates. Each template might look something like this:

<div id="loginPanel">
    <div style="font-size: 14pt; font-weight: bold;">
        Zifmia Login Form<span id="loginMessage" style="font-size: 10pt; font-weight: normal;
            margin-left: 20px;"></span></div>
    <hr />
    <table>
        <tr>
            <td>
                <span style="white-space: nowrap;">
                    Username:
                    <input class="login" id="zLogUsername" type="text" onkeyup="javascript:validateRequiredField(this);" /><span
                    id="zLogUsernameError"></span></span>
                <span id="nickNameField" style="margin-right:10px;font-weight:bold;">
                </span>
            </td>
            <td style="white-space: nowrap;">
                Password:
                <input class="login" id="zLogPassword" type="password" onkeyup="javascript:validateRequiredField(this);" /><span
                    id="zLogPasswordError"></span>
            </td>
            <td style="white-space: nowrap;">
                <a id="zLogSubmit" href="#login" onclick="javascript:$MyWeb.controller.login();return false;">login</a>
            </td>
            <td style="text-align: right; padding-left: 20px;">
                <span id="registerNotice">If you don't have an account, please <a href="#showRegistration"
                    onclick="javascript:$MyWeb.controller.showRegistration();return false;">register</a>.</span>
            </td>
        </tr>
    </table>
</div>

This html should be stored in a subdirectory called templates with the name loginTemplate.html. We can use a simple AJAX call to retrieve it:

    var loginTemplate = getTemplate("templates/loginTemplate.html");

    function getTemplate(templateURI) {
        return $.ajax({
            url: templateURI,
            global: false,
            type: "GET",
            async: false
        }).responseText;
    }

The getTemplate function should be placed in a utility class or in the page controller for easy reuse. From here’s simple to create a controller class to display a view template in the correct place in our html page:

function introController() {

    var REG_USERNAME_FIELD = "zRegUsername";
    var REG_PASSWORD_FIELD = "zRegPassword";
    var REG_NICKNAME_FIELD = "zRegNickname";
    var REG_EMAIL_ADDRESS_FIELD = "zRegEmailAddress";

    var LOG_USERNAME_FIELD = "zLogUsername";
    var LOG_PASSWORD_FIELD = "zLogPassword";

    var viewContainer = "#viewContainer";
    var usernameField = "#zLogUsername";
    var nicknameField = "#nickNameField";
    var regErrorPanel = "#regErrorPanel";
    var loginMessage = "#loginMessage";

    this.introTemplate = $Z.getTemplate("templates/introTemplate.html");
    this.loginTemplate = $Z.getTemplate("templates/loginTemplate.html");
    this.registrationTemplate = $Z.getTemplate("templates/registrationTemplate.html");

    this.init = function (message) {

        $(viewContainer).hide();
        $(viewContainer).html($(this.loginTemplate).html());

        var zLogUsername = document.getElementById(LOG_USERNAME_FIELD);
        var zLogPassword = document.getElementById(LOG_PASSWORD_FIELD);

        setRequiredValidator(zLogPassword);

        if (message != null && message != "") {
            $(loginMessage).text("(" + message + ")");
        } else {
            $(loginMessage).text("");
        }

        if ($Z.username != "") {
            //
            // We know the username and nickname, but the user is logged out.
            //
            $(usernameField).hide();
            zLogUsername.isValid = true;
            $(nicknameField).show();
            if ($Z.nickname != "") {
                $(nickNameField).html('<a href="#changeUser" onclick="javascript:$MyWeb.controller.changeUser();">' + $Z.nickname + '</a>');
            } else {
                $(nickNameField).html('<a href="#changeUser" onclick="javascript:$MyWeb.controller.changeUser();">' + $Z.username + '</a>');
            }
        } else {
            //
            // We don't know anything about the user.
            //
            setRequiredValidator(zLogUsername);
        }

        $(viewContainer).append($(this.introTemplate).html());
        $(viewContainer).show();

    };

    this.changeUser = function () {
        $Z.username = "";
        $Z.saveSessionData();
        this.init();
    };

    this.login = function () {
        var zLogUsername = document.getElementById(LOG_USERNAME_FIELD);
        var zLogPassword = document.getElementById(LOG_PASSWORD_FIELD);

        $Z.login(zLogUsername.value, zLogPassword.value,
                function (zifmiaLoginViewModel) {
                    if (zifmiaLoginViewModel.Status == "0") {
                        $Z.username = zRegUsername.value;
                        $Z.authKey = zifmiaLoginViewModel.AuthKey;
                        $Z.nickname = zifmiaLoginViewModel.Nickname;
                        $Z.saveSessionData();
                        $ZWeb.onLoad();
                    } else {
                        $(regErrorPanel).text(zifmiaLoginViewModel.Message);
                        $(zLogUsername).focus();
                    }
                },
                function (xhr, textStatus, errorThrown) {
                    $(regErrorPanel).html(xhr.responseText);
                }
            );
    };

    this.showRegistration = function () {
        $(viewContainer).hide();
        $(viewContainer).html($(this.registrationTemplate).html());

        var zRegUsername = document.getElementById(REG_USERNAME_FIELD);
        var zRegPassword = document.getElementById(REG_PASSWORD_FIELD);
        var zRegNickname = document.getElementById(REG_NICKNAME_FIELD);
        var zRegEmailAddress = document.getElementById(REG_EMAIL_ADDRESS_FIELD);

        setRequiredValidator(zRegUsername);
        setRequiredValidator(zRegPassword);
        setRequiredValidator(zRegNickname);
        setRequiredValidator(zRegEmailAddress);

        $(viewContainer).show();
    };

    this.register = function () {
        $(regErrorPanel).text("");
        var zRegUsername = document.getElementById(REG_USERNAME_FIELD);
        var zRegPassword = document.getElementById(REG_PASSWORD_FIELD);
        var zRegNickname = document.getElementById(REG_NICKNAME_FIELD);
        var zRegEmailAddress = document.getElementById(REG_EMAIL_ADDRESS_FIELD);

        $Z.register(zRegUsername.value, zRegPassword.value, zRegNickname.value, zRegEmailAddress.value,
                function (zifmiaRegistrationViewModel) {
                    if (zifmiaRegistrationViewModel.Status == "0") {
                        $Z.username = zRegUsername.value;
                        $Z.nickname = zRegNickname.value;
                        $Z.saveSessionData();
                        $ZWeb.controller.init(zifmiaRegistrationViewModel.Message);
                    } else {
                        $(regErrorPanel).text(zifmiaRegistrationViewModel.Message);
                        $(zRegUsername).focus();
                    }
                },
                function (xhr, textStatus, errorThrown) {
                    $(regErrorPanel).html(xhr.responseText);
                }
            );
    };
}

Note there are many other things happening in this controller including ajax calls and handling user interactions. The view is shown to the user through a jQuery call (which can be done with simple DOM manipulation):

        $(viewContainer).hide();
        $(viewContainer).html($(this.loginTemplate).html());
        $(viewContainer).show();

So that’s it. You have a main controller in your index.html page that can be access by using $MyWeb at any time, you have varied controllers that are at $MyWeb.controller that have methods that can be called from your html. All of your HTML is in separate files for easy editing and reuse. This is a simple, yet effective way to separate and manage your AJAX/jQuery/JavaScript enabled website.