Without the right processes and tools in place, offshore software development can be a minefield, in which everything seems out of control and risks are everywhere. Done right, using modern components and know-how, it can be a pleasure and incredibly productive. We’ve been running FP Complete as a highly distributed company, with engineers across North America, Europe, and Israel, since 2012. And we’ve helped many companies with their own offshore and distributed projects.
What are some of the risks in offshore software development, and how do we use good engineering to solve them?
The quickest path to trouble in a remote project is vagueness on the goals and requirements. Even a local team can go astray when technical and process issues distract from the features users need. The risk is even higher with a remote team that doesn’t meet users over lunch or in the hallway. Managers rush the team into writing applications, without first getting the needs and priorities clear and well-documented.
About half of a project’s success is determined during the first 10% of the schedule. That’s when we discuss what is really wanted, and make sure that designs are centered around the user’s real goals. Requirements should be in writing, in a shared repository -- and if later changes are requested in a meeting or phone call, or via email or text chat, these should be recorded as formal, approved modifications to the requirements.
As a client or end-user of an offshore software development project, ask yourself: “Is there something that would technically match what we’ve written, but still wouldn’t meet our needs?” If so, your written requirements are not complete -- so amend them, and make sure you alert the team any time an amendment is made.
The great thing about a remote team is that they can focus specialized skills on implementing what was requested, without distraction from politics or other issues. But they will implement what was communicated, not what was assumed to be “common knowledge.” There’s no such thing as common knowledge. Never assume your remote engineers somehow guessed what you meant!
On large projects, to help with tracking, check-ins of major new coding work should include a comment stating, by number or title, which requirement this check-in is meant to advance. Ideally, each requirement should be matched with tests or criteria that inarguably verify whether the requirement is met.
When we work on medical-device software, we employ this concept to the maximum. Every requirement listed must be traced to a recorded decision to approve it. Every requirement must have a numbered test that shows it was met. Every check-in must have a numbered requirement that justifies the change. Every build must be trackable from a series of justified check-ins, and every deployment must be trackable from a specific build and a specific toolset. Never should a feature appear in a production system that can’t be traced to an approved requirement. FDA approval requires formal quality.
On smaller projects, we streamline the process to suit the need. Fast-moving internal and departmental systems may use live meetings, Slack channels, or emails to approve changes, and requirements may be listed in JIRA tickets or even shared text documents or emails. But in every case, something in writing should record the proposed requirement and whether it was approved.
Typically a modern engineering team will be distributed across several locations, and often two or three companies. People will be added to the team during the project, technologies will evolve, and solutions will become more complex. Combine these issues, and you have the potential for growing confusion -- but it’s easily prevented.
When we were approached by a cutting-edge FinTech (financial technology) company, and by a major life sciences company, neither could get their software builds done reliably in their distributed teams. What had worked for experiments was not scaling up to work for production projects. Weeks could go by between internal releases. And when a new team member joined, perhaps in a new location, there was no clear way to get them up to speed. We assembled shared, managed engineering tool sets that solved these problems very quickly: a release that builds on one machine build the same on every machine.
Ensure that all team members -- local and offshore -- are building their work on the same set of engineering tools. At FP Complete we like to develop in Haskell, and we ensure everyone is using Stack to manage their environments, and on larger projects, we use Docker to create a standardized development environment that all team members can run in a virtual machine. To stay in close communication we use Slack constantly, we track issues in GitLab (or our client’s preferred issue-tracking system), and we share our code using Git-based version management systems.
Ensure that everyone joining the team goes through a standard orientation, with a shared checklist online that everyone can see (and add to if needed), including links to all needed getting-started materials and tools.
All-hands meetings are inefficient with an offshore or distributed team, with time zone issues adding another layer of complexity to what is already an inefficient way for big teams to work. Instead, use shared databases, repositories, and concise reports -- all in written form -- and keep a team channel open in Slack or a similar instant messaging tool. Letting people work asynchronously -- and making sure what was said is available to people who weren’t online at the same moment -- really improves team coordination.
Many IT projects are stuck in technical practices that made sense several years ago, but that live on unexamined. Is it time to revisit our engineering assumptions, and see if we can lose some constraints?
One common example is the decision to do all work in a single programming language -- indeed, to treat a whole solution as if it were a single program. This kind of ultra-uniform, monolithic, centralized design is a recipe for paralysis -- as well as for hard-to-maintain spaghetti code. Working with remote engineers brings this issue to the forefront because you want the kind of speed and productivity that come from letting them move ahead with their work in a decoupled fashion. Mature industries know that welding isn’t hammering, steel isn’t plastic, and batch processing isn’t stream processing.
The future of software is in API-driven or Service Oriented Architecture (SOA). Think of your solutions as a series of SaaS components or “services,” each of which has its own specification and features. Each service can be designed and built separately, component-tested separately, deployed and maintained separately. Each can be written using the libraries, data structures, and language best suited to the task. The user interface team doesn’t need to code like the database team, for example.
Each service exports as a well-defined interface (API) that is well defined in a shared spec document. This lets you identify specific services that you want your remote engineering team to create, enhance, test, and deliver. They can work on their own accelerated schedule even as your in-house team works on its own schedule.
If you do bring in an outsourcer with different expertise from your own, ensure that they’ll be showing someone on your team how to use the tools they’ve used. Knowledge sharing should be a built-in benefit of bringing in outside experts.
When you sit with someone every day, there are a hundred little moments to provide feedback. When your engineers are far away, these moments are farther between, so you need to make them count.
Define and agree on the criteria for quality and completeness. A certain number of transactions per minute? Zero user interface bugs above a certain severity level? Requirements 1 through 7 are all met? There should be little room for disagreement about whether something “works.”
Divide the project into stages, each ending with delivery and acceptance. This is when your offshore developers declare “we believe we have met 100% of the criteria for milestone 2” and they show you the results of their tests that demonstrate this to be true. Even then, consider whether you want to have designated staff on your side to review the delivery and accept it (or send it back for corrections) based on the agreed criteria.
If the project is long, schedule update meetings even between milestones -- at least every week if the project is very collaborative, at least every month if the remote team is taking full responsibility for cleanly separated projects. Don’t wait to hear about progress, or lack of progress, at the end. A lot of your ultimate happiness will come from keeping your engineering vendor informed about your own concerns. This is especially true if the project is innovative, because you may realize that your own priorities are coming into focus or changing during the project’s lifespan.
It’s tempting to take a very firm hand and specify exactly how you want something built, down to the last detail. But this limits your upside. Instead, talk to your developers about the results you want, and encourage them to bring in existing techniques -- perhaps even large existing software components -- to get you more results in less time.
Between your vendor’s existing skills and expertise, and the powerful features available on cloud computing platforms, and the huge amounts of open-source or licensed software already available on day 1, much of the solution you need has already been created! Ask your offshore team to investigate, and report back on, ideas for reusing existing technology. Modern software development is often as much about thoughtful reuse and Lego-block assembly as it is about writing new “virgin code.”
Do leave room for your offshore team to make suggestions. If you hired a team incapable of having good ideas, you didn’t choose the right team. :-) Ask them to bring to the table their expertise from past projects, as well as ideas that come up during implementation -- you may end up getting more progress, in less time, than you anticipated. But insist any new goals go through the approval and prioritization process.
The less you constrain your developers to use one specific technology or design -- and the more you challenge them to bring further ideas to the table -- the more you are going to benefit from having a larger, distributed team. A day spent on research and design may get you more results for your money than a day spent rewriting the wheel.
Different projects require different skills and, frankly different amounts of expertise, robustness, and even quality. If you’re going to build a state-of-the-art, highly scalable, unique data-analysis server, you won’t want a team whose last project was a toy. On the other hand, if you’re making a department news website, you just don’t need a high-end engineering firm specializing in global document-sharing architectures.
Consider whether your overall IT system is going to be small or large, conservative or innovative, basic or advanced. Consider whether you want a firm to do exactly as they’re told, or to bring expertise and judgment to the task, or even to help your own team increase its average skill level and technology platform. Spend on reusable technology and innovation, and on systems that will save you time and effort -- in other words, invest in your IT factory using highly skilled providers. Save on routine and reuse -- in other words, streamline daily operations using highly efficient providers.
IT projects are measured in time, not just money. To get the most out of the time and money you invest, don’t neglect the role of sequencing and stepwise progress.
A common mistake is to write a grand specification that describes a finished application, and just say “tell us when it’s almost done.” That sounds like a handy way to use a contractor, right -- one less thing to think about? Since you and your contractor are distributed, this can hide issues or misunderstandings until it’s expensive to fix them. And even if the project is 100% on track, you don’t start collecting the benefits until final delivery. Who’s got time for that?
Talk with the engineering manager to break your project into a series of milestones, or mini-releases, to deliver interim amounts of features during the course of the project. This way you can actually see that the project is making progress, and ideally even start using the software before the final version with more capabilities is done. If the project is something really useful, you may start earning back your time investment within just a few months of the project launch and end up ahead by the day of final delivery.
At FP Complete, we start most engineering projects with an assessment stage in which we scan the current systems and identify opportunities for progress, a first project phase in which we aim for a quick win on a well-identified problem -- typically followed by a second project to deliver another helpful win, meanwhile building the working relationship for more and more incremental deliveries. Why launch a single, monolithic ship when you can launch a never-ending stream of boats?
You are the decision maker, and by hiring an offshore or remote team, you are choosing a path forward. In exchange for some budget -- and some of your own time and trust -- you expect big wins in expertise, time-to-market, quality, technology, and cost-effectiveness.
How can an offshore team win your trust? By showing you their expertise, their track record, and their technology, sure -- but also by showing their willingness to understand your real needs, to look under the covers, to communicate both ways, and to deliver measurable results in a series of visible steps. Choose a vendor you can trust, learn each other’s style of communicating and prioritizing, and then start building a pipeline of successful projects you can do together, one after another.
Do you like this blog post and need help with industrial Haskell, Rust or DevOps? Contact us.