Throughout the 2000s, journalists Walt Mossberg and Kara Swisher hosted eleven All Things Digital (ATD) conferences. At ATD, they interviewed execs at some of the most influential tech companies in the world. Among those interviewed, the then-CEO of Apple Inc. Steve Jobs appeared a total of six times. It was in 2010 that Jobs gave his final ATD interview, before his death in late 2011. At the time, Apple had released its first iPad and—following in the footsteps of the iPhone in mid-2007—shipped software that lacked support for Adobe Flash, an exceptionally popular browser plugin that powered many of the then-advanced and desktop-grade web applications, including YouTube. The move was unpopular and seen as detrimental to end users who were unable to use many of their favorite web applications on an iPad. This was brought up by Mossberg during Jobs’ last appearance. Mossberg asked if it was the best decision for consumers, to which Jobs responded:
“Apple doesn’t have the most resources of everybody in the world and the way we’ve succeeded is by choosing what horses to ride really carefully, technically. We try to look for these technical vectors that…have a future and that are headed up.
Different pieces of technology kind of go in cycles they have their springs and summers and autumns and then they…go to the graveyard of technology and so we try to pick things that are in their springs and if you choose wisely you can save yourself an enormous amount of work…and you can really put energy into making those new emerging technologies great on your platform.”
Jobs’ method of selecting which technologies to support in their products is one that can be replicated with a consultant mindset. While it is important to select the best libraries, frameworks, and languages for our project right now, we must also consider where technology is going in the future and whether our application (and its included technologies) can evolve with it.
Vue.js Migration: an Example
We worked with a subsidiary of a multi-billion dollar services company that approached us with an interesting project. They had a series of internal-use web applications that were built on a stack of .NET APIs with a KnockoutJS frontend. While they continued to maintain their existing applications, the client correctly determined that KnockoutJS—with the latest, stable release being nearly three years old—was mainly used by legacy sites that had not migrated to UI libraries like React or Vue.js. As a result, the client was interested in moving to Vue.js—an MVVC-patterned library for building UIs that credits KnockoutJS (among other libraries like AngularJS) as influencers to their APIs.
The client had already experimented with building a small, proof-of-concept application that gave them the confidence that Vue.js was a promising library for their developers. However, they were seeking some guidance on how to build their application in a way that would ease the transition to Vue.js in the medium- to long-term while maintaining backward compatibility for parts of the application that had not yet been ported. Additionally, the client developers, who had strong backgrounds in C# and KnockoutJS, were new to Vue.js and wanted to ensure that they were building for the future. They wanted to be sure the design patterns and approaches they were using to begin this multi-year transformation were the right ones.
During the initial assessment, the client asked us to review the code for the proof-of-concept application they had created in Vue.js and offer feedback to be captured in a technical strategy that would shape our approach. The defining characteristic of this project was clear: this was a large-scale effort that would be done over a long period of time. With that, a number of considerations would need to be made to build for the future.
What is the correct selection of libraries and languages in their technological ascendency that will still be used by the time migration is completed?
This was a migration project that would take much longer since it involved migrating an existing large-scale application and prioritized stability and predictability over turnaround. To do this, we settled on rebuilding specific sections of the application in Vue.js with the client developers. The then-recently released Vue.js 3 was a natural long-term choice for its flexibility, speed, and the new Composition API which would give us more flexibility when composing smaller logic in components than what was previously available in Vue.js mixins.
What frontend libraries and languages can we select that are the most familiar to a predominantly backend set of engineers who would be cycled on and off this long-term project?
With the framework selected, we moved on to additional considerations for a predominantly backend set of client engineers. With the team well-versed in C#, adding TypeScript to the application made sense. Its support for strong typing gave the added benefit of avoiding potentially slower polymorphic calls and catching run-time errors related to variable typing before runtime. Additionally, the support for types allowed us to define complex data structures that could eventually be used throughout the growing application. Finally, using a typed language like TypeScript would also give developers additional guardrails to place around their code—this, in turn, would give newly-onboarded developers clearer guidance on the parameters of functions and components. It was an important consideration since developers would be cycled on and off of the project over its lifetime.
How can newly-migrated sections of the application continue to operate alongside the yet-to-be-migrated sections of the application?
Lastly, we needed to find a solution for making sure that our project was clearly structured and organized to allow it to grow alongside an existing application. We set out to avoid a scenario where two codebases supporting a single application led to disorganization and obscurity. When it came to how our application interacted with data, we wanted to be sure to find a solution that would scale as services grew. Additionally, we wanted to minimize interaction between individual components and the application store. This would allow us to generalize components to a component library to speed up the development of other applications migrating to Vue.js. We decided to use the “data down, events up” approach where a single or few components would handle interacting with the application store, and would pass data as properties to components. Then, user interactions (events) would be passed back up to the apex (main) component which would, in turn, pass event data back to the application store. In this way, the apex component would act as a sort of capillary exchange—retrieving data via a set of public application store getters and setting data in the store via bubbled events from children components.
Using Vuex as our application store, we’d abstract API services (like authentication services, data retrieval APIs, etc) to a services layer that would operate underneath the application store layer. By distinctly separating out the mechanics of the application and orthogonalizing the relationship between our services, data, and component layers, we were able to identify contracts between each layer and compartmentalize changes and refactors to each layer. Additionally, the agreed-upon contracts between layers allowed us to stub out API services for our components layer to allow component prototyping even before the APIs were completely engineered.
A Consultant Mindset Led to Future Success for This Client
This client approached us with a simple question: How can we build our application for the future and adopt a system that would allow us to approach migrating our application iteratively? With a consultant mindset, and taking an inventory of the defining characteristics of the project, Sparkbox was able to adopt the correct technologies and software design patterns that would set the project up for long-term success. By the end of the engagement, we worked with client engineers to finish migrating a specific section of the application and finished with an offboarding session to outline the next steps.