Abstraction is a technique for arranging computer systems in such a way as to reduce the complexity of interacting with them. The system makes a certain complexity level available for other systems to interact with, while suppressing some of the inner workings. Programming languages, for example, are abstractions over assembly languages, which are abstractions over machine-level languages. Efficient use of abstraction is essential to writing maintainable, extendable software. Identifying when to abstract or when to incorporate an existing abstraction requires serious consideration. However, moving forward with the wrong abstraction could complicate adding new features, as engineers struggle to extend the abstraction to support them. Sandi Metz discusses this drawback to abstraction in a blog post, where she stresses that “duplication is far cheaper than the wrong abstraction.”
Earlier this year, we launched Path, our comprehensive financial planning and investing solution. We built a mobile experience that enables clients to save for major milestones and explore a range of future scenarios, allowing them to answer questions like:
- Can I live my current lifestyle in retirement?
- How much will I be worth then?
- How much should I be saving today?
Path launched with a focus on helping clients understand where they stand today as well as plan for their long term goal of retirement, but we knew that we would soon build in richer functionality around other goals, like purchasing that ring that says to someone you’d like to plan the rest of your life together, planning for a future home, and eventually saving for your kids’ college tuition.
The experience we set out to build needed to communicate complex financial scenarios in an intuitive, interactive way. To this end, we built a custom chart that doesn’t fit into any archetypes. This visualization has styled areas to denote different life stages, unique hover and drag interactivity, and it updates in response to user-inputted changes to key financial factors. If you haven’t yet, I encourage you to give it a spin. Here’s a GIF of it in action:
D3 Abstraction Libraries
At the outset of implementing Path, the team considered using a D3 abstraction library to speed up development time by cutting down on the necessary setup for visualizations. The open source community has built several libraries and utilities on top of D3 for this purpose. A comprehensive list can be found here. There are libraries that work well with different web frameworks (React, Angular, Ember…), libraries for certain types of charts (pies, maps, time-series…), even a library for generating static visualizations in a node server. The point is, there is a lot of currently-maintained work the community has done that may be perfect for your team to leverage. However, we opted not to incorporate any of these libraries.
We’ve designed and built Path iteratively with very custom patterns, animations, and interactivity. One example of something that would have been challenging to accomplish by relying on an abstraction library is our use of transitioning clipping paths. The Path graph is split up into two sections: one for the period prior to retirement, when a client is building up their nest egg, and one for the period after retirement. Clients can drag around a slider on the bottom of the graph to change their retirement age. It’s critical the graph update smoothly in real-time so clients learn how things work through direct manipulation and see how their decisions today impact their long-term financial future.
Our initial approach was to draw only the relevant data points for each series (i.e., current date through retirement date for the first one and retirement date onwards for the second). However, creating smooth transitions with this approach was challenging due to the changes in the numbers of data points for each as the user changed the retirement age. We ultimately solved this by drawing both series to take up the full width of the graph and applied clipping paths to each to hide the non-relevant data points. As clients interact with the graph to see the impact of changing their retirement age, we transition both the series and the clipping paths. This results in a smoothly transitioning chart with dynamically changing series sizes (as demonstrated by the GIF above).
Due to the uniqueness of the requirements, the above solution would have been more difficult to implement with an abstraction over D3. Additionally, the expected extensions to our product may have been challenging with said abstraction. Even if we had implemented an abstraction that worked well today, it could have proved challenging to use for upcoming product features.
Through our experience building Path we’ve learned that existing D3 abstraction libraries do not currently provide the leverage required to create truly unique visualizations and highly-customized interactions. There are trade-offs involved with every technological decision. In the end, what matters is to opt for the choice that best aligns with your team’s optimization principles. We’ll continue to evaluate this choice as we build out a revolutionary financial services user experience.
Nothing in this communication should be construed as an offer, recommendation, or solicitation to buy or sell any security. Wealthfront’s financial advisory and planning services, provided to investors who become clients pursuant to a written agreement, are designed to aid our clients in preparing for their financial futures and allow them to personalize their assumptions for their portfolios. Additionally, Wealthfront and its affiliates do not provide tax advice and investors are encouraged to consult with their personal tax advisors.
All investing involves risk, including the possible loss of money you invest, and past performance does not guarantee future performance. Wealthfront and its affiliates rely on information from various sources believed to be reliable, including clients and third parties, but cannot guarantee the accuracy and completeness of that information.