Cheap is Expensive

Cheap is Expensive

The common law of business balance prohibits paying a little and getting a lot – it can’t be done. If you deal with the lowest bidder, it is well to add something for the risk you run, and if you do that you will have enough to pay for something better.

Attributed to John Ruskin

The cheaper the software development is, the more expensive it will be. When people seek to develop a product, it can be hard to understand all the costs that go into it. Software development can be like an iceberg in which 90% of the structure isn’t visible to the end user.

Beyond wanting to retain as much money as possible, cheap development can be appealing because it can seem like:

  • Development can occur anywhere
  • The software functions are simple
  • When the software is completed, other, more visible “higher value” items can progress
  • Software development isn’t that hard
  • Development really can occur anywhere. The problem is that accountability can be hard to ensure from a distance. When you don’t have the ability to directly supervise the hiring process, training, and code quality you have no way of knowing what you’ll really get. There are things you can do to mitigate the uncertainty that occurs with remote or offshore work, but they cost money and time and require expertise in software development. If you don’t have someone on your team with that expertise, remote/offshore development is a huge risk. Supervising a remote team is not the same as supervising a team on-site.

    Simple does not mean that a function is easy or fast to make. A really thorough exploration of the implication of the product can show the unintended consequences and supporting structures to operationalize the features. If there is any data that is supposed to be stored and retrieved, then your product will need some sort of storage and database.

    If your “high value” items are built on a fragile piece of software, then that value will quickly be lost as it breaks and loses customers or never functioned in the first place. You can’t rob Peter to pay Paul. That never turns out well.

    It is entirely possible for a developer to put a pretty face on a project to cover a mess of chunks of broken code underneath. Worse than that is a product that functions at the moment of release, but would require a complete rewrite to update because the developer didn’t architect the project well. Yes, many people can write some code. That is not the same thing as architecting a new product.

    Software development, like a lot of skills, is progressive. When you hire an inexperienced developer, you are paying for their education as much as you are their code. That balances out on a sufficiently large team and is part of the normal arc of growing new members of any profession. If you are going the cheap route, you’re probably going to be working with more inexperienced developers and that will be reflected in the ultimate cost.

    We’ve seen projects in which the initial development was an oozing pustule of code with functions distributed widely throughout because no one with sufficient expertise thought through the architecture and the implications for each of the functions/features upon it. This code quickly drags down the whole project when later developers attempt to update or add a feature and find they can’t because the scattershot code can’t be modularly replaced or improved. You can’t remove just the tumor, because the cancer has spread.

    Even worse than that is when a business falls into the sunk-cost fallacy and just can’t let go of some really nasty and fragile code. Rather than scrap it and start over, they spend an insane amount of money frankensteining more code on top of it to keep it limping along.

    The time you spend untangling a poorly developed product and repairing it costs more than the expense of the developers to test and correct the code, it costs customers. You lose revenue the product would have earned in the delay coming to market.

    There is a mistaken impression that producing software is so easy that high school and college students working alone are creating billion dollar companies. It is true there are prodigies; rare individuals whose monomaniacal devotion to a single product is the foundation for something larger. Though even they had early supporters and funders to enable their seed of an idea to scale.

    Even though finding a bargain on development is a bad idea, there are still many ways to prevent your project from bleeding money.

    Be wise about your development expenditures:

  • Map out the functions of your product to prevent wasteful redevelopment and inadequate architecture.
  • Learn about the process of software development to become an informed consumer so you understand what the developers are doing if not how they are doing it.
  • Have a software development-specific contract; buying software development is not the same as other services.
  • Get clear Statements of Work that show exactly what will be developed and what that code will do.
  • Have highly specific Acceptance Criteria and a plan for remediation if the software doesn’t meet that criteria.
  • Being wise about your expenditures will save you the costs associated with being unprepared and uninformed. Be frugal, but not cheap.

    Cheap is expensive, expensive is cheap.

    5 Important Mobile UX Areas People Usually Forget

    5 Important Mobile UX Areas People Usually Forget

    At Salty Dog we help clients to define their app. Many clients know how they want their app to solve a particular problem but haven’t figured out how the app will look from the perspective of their customers.  There are some key UX areas they often forget that can have a huge affect on the user experience.

    Here are some of the most easily overlooked UX areas:

    Login and Registration

    Login and registration are usually the first part of an app your user will see. Some commonly forgotten sub-use cases are: forgotten password, registering email, forgotten password but haven’t verified their email, or re-sending email verification.

    Forgetting passwords can happen more frequently on mobile devices. It can get really annoying for a user to try a bunch of passwords, then have to go back to the main website to request a new one.  This is amplified if the registration requires email verification, and they are denied a new password because they haven’t completed this process.

    The solution to these issues is to remember some of the more subtler use-cases. Here are the  use-cases for a complete login and registration experience.

  • As a user, I would like to register/create a new password-protected account, in case I don’t have one yet.
  • As a user, I would like to authenticate with the app, so that my information is protected.
  • As a user, when I start the app I would like to know if I haven’t validated my email address if I haven’t, so I know to look in my inbox or spam folder.
  • As a user, I would like to be able to resend the email verification in case the old one is expired or lost.
  • As a user, I would like to be able to set a new password via my validated email address in case I’ve forgotten my old one.
  • As a user, I would like to be able to log out of the device, in case I want to restrict access or log in as a different user.
  • As a server administrator or app owner, I want a way to log a user out, in case there is a good reason I want them to re-authenticate.
  • Application Updates

    Sometimes it is necessary to make changes to the way the app works and require users to update. For example, there might be a change to the way the server works that breaks any previous versions of the apps that haven’t updated, or there is a really important security fix.

    The solution for this is to provide a way to make sure the user updates the application, and then gracefully degrade functionality if they do not update. A simple flow outline might work like this:

    1.On app start, connect to the server supplying the version of the application.
    a. If the version does not need to be updated, then respond with an OK.
    b. If the app DOES need to be updated, then respond with a “needs update”.
    2.If the app received an “needs update” response from the server, then:
    a. Inform the user they need to update.
    b. Let the know that functionality of the app will be impaired if they do not.
    c. Give them an easy way to facilitate the update such as a button that takes them to the App Store or Market app to update.

    Important Notices

    It is really important to be able to send notifications/notices to the user. The purpose can be anything from letting them know about planned server maintenance, other companion applications, updates/upgrades to the functionality,  or bug fixes.

    What makes this so critical is because of how difficult it can be to communicate with the user. You need to communicate with them so you can set their expectations about app functions and changes. In the absence of information, the user may jump to negative conclusions that can result in bad reviews, or worse, uninstalling your app.

    The fix is relatively easy and accessible: add a way to send notifications to the user. There are many third party services that can do this. Some even allow targeted notifications to segments of your users.

    Alternatively, you can implement your own solution. The messages can be displayed using webview controls, allowing you to point the user to blog posts or release notes. The app just needs to be smart enough to know if the user has seen the notification before so they don’t get spammed with notifications.

    Network Problems

    Issues related to the network or connectivity are ignored a lot of times, and are only discovered in testing or when a user has issues with it. These fall in three basic categories:

    1.Server issues. The server might have an issue. The cloud provider may decide to reboot your server. Even though the network is functioning correctly, the server may not respond.

    2.Network issues. Sometimes there are outages either at the ISP/provider level or somewhere in the backbone.

    3.Device connectivity. It could simply be an issue with network connectivity from the device. The user is out of cell range, or service quality is low.

    4.Planned outages. The server might need to be upgraded, or the system restarted.

    There are two basic ways of dealing with this. First, design the app with lack of connectivity in mind. For example, if the app cannot reach the server then handle it gracefully. When the network is not reachable, you can give an indication in the app so the user has an idea of what is happening. I’ve seen some apps show an indicator in the title-bar.

    Second, leverage the Important Notices suggestion above. If you’re using a 3rd party notification service, then you can inform users that you’re aware of the outage and when they can expect it to be available again.

    Interacting With Someone Who Doesn’t Have the App (Yet)

    When designing social apps such as chat, it is easy to forget about the case when one person has the app and they wish to interact with someone else who doesn’t. This is important because it can provide a viral way of gaining more users.

    We’ve blogged about this in detail here and here.  The basic problem is how to interact with someone who doesn’t have the app yet. Once you solve the interaction problem, how you can turn that into a seamless onboarding process for a new user.

    The answer is to use something called deep-linking in conjunction with SMS messages and a bit of magic from the iOS web-view control and Android App Store broadcast message. This allows you to send an invite link to someone over SMS, which sends them to a landing page that includes links to the appropriate web-store to install the app. After they’ve installed the app cookies can be used on iOS or broadcast messages from the Google Play Store App, to let the newly installed app know there was an invite from someone else.

    This allows an invite to go to someone without the app, them to install the app, and then pick the invite up from where they left off as if they had the app installed in the first place.


    When making your mobile project it is important to remember what happens after the initial release and use. As the overall quality of apps has improved, sensitivity to clunky apps has increased. Failing to include these user stories is very likely to result in a user deleting your app.  These user stories should become a part of your larger release strategy to help you plan for ongoing updates, user engagement, and to ensure that you have the infrastructure in place to support users when they have a problem with the app.

    Iterations Keep You in the Loop

    Iterations Keep You in the Loop

    There are some developers who will do all the development prior to revealing the product to their client. This is a great way to get something other than what you had wanted and have little to no recourse to get it changed or avoid cost overruns.

    With iterations, you are never surprised by the product delivered to you.

    At Salty Dog Technology we use an iterative process.  The iterative process ensures that the client is getting the product they want and need.  

    An iteration is a block of work, usually encompassing a single function/feature or group of related functions/features.

    An example of a single iteration:

    • Describe the work to be done in detail in a Statement of Work. 
    • Get approval from the client.
    • Wireframe work to be done.
    • Get approval from the client.
    • Code the functions/features.
    • Demonstrate functioning of functions/features to the client
    • Deliver code written to client

    An iteration usually takes anywhere from 1 week to 1 month, depending on the turnaround time for questions and the amount of work to be done.  Iterations help you to minimize risk, as you are constantly getting to see/use/take possession of work done throughout the process.   

    Another advantage of iterations is that course corrections can be made early. … explain… … Work occurs on your schedule.

    For example: Imagine you want an app. You have imagined that your app has three core functions. With the iterative process each function may be an individual iteration.  After coding the first function, we realize that there are multiple possibilities for the way that users are directed to the second and third functions.  You get to use the app and we discuss which of those possibilities make the most sense for your app.  You chose one, and we code the next iteration.  The finished product contains the features the way you wanted them to appear based on your in-depth knowledge of the market for the product/use of the product.  

    Now imagine that you approached a developer who agreed to make the app for you but who doesn’t work iteratively or in partnership with you.  You tell them what you want the app to do.  They begin coding and when they face a decision point- they make it- you are never consulted.  You receive a completed app.  It might be what you wanted.  It might not.  You don’t know what you’ll get until the very end because you were forced to take a blind leap of faith that they would finish it appropriately.  

    We don’t ask you to walk off a cliff and hope there is a net below to catch you.

    We want you to feel confident that the product being built is what you want and need.  We want you to be the one to direct the project and make choices.  We want to set you and your product up for success.   

    So- when you hear us talking about iterations- this is what we mean.  It is one of the many ways that we keep you in charge and in the loop.  

    Client-Centered Engagmenet

    Client-Centered Engagmenet

    We believe that responsible, client-centered engagement results in high-quality products that people are happy with.

    Client-centered engagement means that the client is at the center of and drives the process. It is a concept I borrowed from therapy, as I was a social worker in my previous career and it describes how we work at Salty Dog.

    Too often a conversation is just one person waiting until the other stops talking so that they can talk. At Salty Dog Technology, we work hard at listening and understanding. We want to hear your ideas and we want you to know that we see the project the same way that you do. Listening may take the form of a phone conversation, a face-to-face meeting, or an email. Whatever the format, for the duration of the conversation, you are the sole focus. We reflect back what we hear so that you have a chance to clarify your statements.

    Have you ever left a conversation where both people are saying the same thing, but later you find out that you both understood something different? Imagine that you and a friend agree to go see a movie. You’re thinking of something with lots of explosions but they’re planning to see a comedy. You don’t realize that you left the conversation with different expectations. We call this “false closure.”

    To avoid false closure we put together outlines, draw pictures of screens, and make mock ups to depict what we heard in the conversation with you. You have the chance to consider how you would like your screens to look and make adjustments before we begin coding. We are experts at design and programming, but that means little if the product isn’t what you had wanted.

    We check in with you a lot. If you call us and want to talk about your project, we will make the time to listen. Your communication isn’t getting in the way of the work, it is the work. It is the best interest of the project to keep you updated with progress reports. As each portion is finished, you will be able to see and interact with it. If we encounter an unexpected roadblock, we will contact you right away and discuss possible courses of action. We will never just surprise you with a bill and a solution we made up ourselves.

    Part of the Salty Dog process is to work in iterations- small chunks of work that result in the next piece of the product. Because we work iteratively, at the end of each cycle, you’ll have pages to look at and functionality to try out. You can verify it is working how you wanted and make any needed changes.


    You get the source code at the end of each cycle. You are the owner of your code, it gets in your hands at stage of the project. Your project shouldn’t be a mystery to you. We’ve all seen the disastrous results that can occur when a contractor doesn’t show or deliver the product until the very end, or worse, never delivers despite being paid. Salty Dog Technology believes that as you pay for the code, you own it and can access it.

    You are the first user that we test your product on. We want you to be happy with how it functions. We want you to see how your idea made manifest works. We will eventually test your product with other people to make sure that it is the best product it can be, but you are the first and most important tester.

    You could be reading this and be thinking that you don’t actually want to talk to us that often. That’s ok, too. We work for you, and take our cues from you.

    We want to build long-term relationships with our clients so that you will come back to Salty Dog the next time you have a project.

    We’re listening- what would you like to tell us?