When we design software, we use design and engineering principles to solve problems, yet in agile teams our solutions get boxed into a finite set of requirements that may not challenge us to consider how an application will change over time. Perhaps we’re working on a code rewrite of an application that includes a new search feature or maybe an analytics program addressing fraudulent behavior or possibly a new greenfield idea altogether. These all share tangible goals relative to the needs of current users.
While its difficult to predict what the application or business will need in the future, considering the future of our code in the methods we employ to share concepts and data practices across the team is vital for product engineering. Lean designs share the modularity and reuse principles, just like code. They also consider the future of the product or service to simplify the experience. It’s possible to build a bridge for the user experience by considering how a solution will change and evolve.
Our engineering practices will have us sketching out concepts for the user interface and writing tests for edge cases that equates our daily efforts to running “code complete” tasks against these requirements as if to suggest that validates the user experience for the solution. Yet, these efforts bear little resemblance to anything a user might see in the UI or ask for directly when using the system.
In reality a codebase will change, evolve, be refactored, and repurposed time and time again, so our designs need to be aligned to the changing nature of the features. Therefore, aging in software isn’t a function of time; it is a function of how we choose to plan or bridge design changes over time.
Case in Point: Design for Change in your Search Features
Company: A leading financial service provider brings payment system online for corporate customers.
Use Case: Design services for application that includes new features for integrated components. Component designs were created to capture requirements for the product team. Research identified improvements for the design to ensure the search api could handle future needs as the product grew.
In the initial design of the UI, neither a service nor the database might have considered other workflows such as list retrieval of results or full-text search capability that would potentially result in a full rewrite of the feature down the road since shared services were being created with a finite use case.
Table: Search Beyond Queries
|Behavior changes||Returns result|
Solution: Future search interface includes a service with advanced features to return a list of results in the user workflow and an event triggered by the query itself. Design updates were made to the service design and the database for the future context.
A search event was designed to create the search results, whether or not the results return a list or are even used in the UI or any future UI.
Table: Search Beyond Queries
|Behavior changes||Returns result|
Business Benefit: The teams were able to concept and reuse the design pattern across the application.
- Decreased cost of engineering and data modeling time
- Small team able to stand up new technology features
- Refactor wireframes to allow teams to visualize and model data
Too often user interfaces ideas are coupled with a service interface or database, making it difficult to share data at any level of scale beyond the context of the UI down the road. We are often less likely to think about how a design or a service will change over time and far more likely to ask questions like: Will the system scale as our user base increases? Will response times be fast enough to keep users happy? Will it promote reuse? In fact, you might be hard pressed to identify a code spec of a system designed to withstand the test of time.
Addressing Data Divergence Problems
In practice, all large systems start to have problems with data quality over time. This is a complex matter, subject to painstaking, laborious, and expensive issues to correct. The root cause of data quality issues can also be difficult to diagnosis, whether it was that the design was never intended to change in the first place or that database itself can’t be shared. Consider a typical business application that loads data from several other systems and stores that data in a database. There is a data model used for the api (e.g., JSON), or during internal automated tests and finally various schemas for any outbound communication. Code needs to be written for each system layer and this code needs to evolve as the respective schemas change.
Semantic issues can also be more difficult to address and often arise between the disparate interests of teams working across the codebase. Consider two companies going through a merger. There will be a host of equivalent datasets that were modeled by each company for different purposes. While some might perceive this as a transformation problem there is potential for far deeper semantic conflicts: Is a supplier a customer? Is a user an administrator or a company user?
As data moves from application to application and from service to service, the user interactions behave a bit like a game of telephone: the context starts out fine but over time the design needs transforms into something quite different and meaning of the data or service changes altogether.
Some of the resulting issues can be serious: a bank whose Security and Product departments disagree on the user experience, or a retailer with a particularly involved customer service workflow who then takes a week to answer customer questions. All large companies with larger, legacy architectures have stories like these in one form or other and they not be the same set of issues faced building smaller web applications.
Designing a component or service also means considering for the future of the solution. While there will always be opportunities for misinterpretations, techniques like designing for change and lean data allow individual teams to develop the operational maturity needed to avoid mistakes in the first place or bridge the impact of them once they happen. When it comes to designing for change, we should be unequivocal about the shared design patterns within system layers as its the very essence of the user experience for the system.