During the last two months, we've been focused on two major features and a bunch of small enhancements for our iOS app.
Search Version 2
As you may have noticed, a new Search engine has been released on our main web application. It generates better results than the previous engine, and provides more options for filtering. This search engine is now available for our iOS app. It's easy to search for work items on-the-go, filter the results by entity type or entity state, and sort them by Relevance or Creation date.
Finally, Time History records have been added to our mobile app! You can navigate to an entity's Time History by tapping its 'History' link. Time records that have been added to the entity are shown in a handy table right in the app. You can easily review, post, and edit records from Time History. To edit a time record, just hold your finger down on it (long tap), and select the “Edit Time” option.
Small, but useful improvements.
- Our mobile client now supports ADFS SSO.
- If your board consists of only one column, the app will show it in paging mode by default.
- There's no need to repeat entity type selections when adding multiple items, because the system will remember for you! The last added entity type and Project will now be saved on the Add tab after entity creation.
- Negative values can now be added to Number and Money Custom Fields.
- System Custom Fields now are read-only (because only metrics should affect these fields)
We appreciate any feedback from you. Please, use the Feedback form in the app’s "Me" tab, or send a message to email@example.com. We'd love to chat.
Click here to download the iOS app.
You can now add a short description to views from View Setup. Users with access to a view can read its description by clicking on the view's title. This View Legend will also include information about card types displayed on the view, as well as view cards, active filters and visual encoding rules. We hope this will help users to better explain and understand what views are showing.
Entity details view: Assign existing entities from Inner Lists
You can now not only create items from Inner Lists, but also assign existing ones. If you are on a Feature details view and want to assign all existing User Stories, you don’t have to open a new view to do it. Just click the Lookup icon from the User Stories list, and select the entities that you need:
Hierarchy in Inner Lists
To help users better understand how different cards are related, we’ve added a hierarchy to Inner Lists. You can find User Stories under the Feature and Iteration levels, with Bugs and Tasks under the User Story level.
Visual Reports: redesigned report creation flow, and some new templates
The flow for creating reports has been slightly changed. As you know, templates from all sources are listed on the initial report creation page. You can select any of them, or create your own via a Blank template. In the new flow, clicking on a template does not immediately lead to report creation as it did before. Instead, you first get a pop-up with source and chart settings. You can make changes there, or close it and select another template. More details here.
We've also added some additional templates: a Process Control chart, and a Stories and Bugs Burn Up by count of records. The Process Control template shows the distribution of Cycle or Lead Time for completed User Stories in a given time frame. The Stories and Bugs Burn Up template tracks completed Users Stories and Bugs against the total number of these entities in a release.
Visual Reports: dynamic annotations
The Annotations UI has been slightly redesigned, with some new functionality added. Previously, you were only able to add plain numbers, but now you are also free to add calculations. Let’s use a Process Control chart as an example. You can add the median of Cycle time or Lead time values as an annotation line. Your reports will calculate this number and display a line at these points. Whenever data is updated, the value for the annotation will be recalculated and the line automatically redrawn.
Visual Reports: progress bar for report updates
We suppose that it makes sense for users to actually know the progress of their report updates, so we've added a progress bar for this action. This bar also displays the count of updated items vs. total items. Moreover, both the status update section and “Update now” button have been moved to the top, closer to this progress bar.
- Inactive users will be highlighted on views
- Entity names will be included in 'Share link'
- Added support for DSL filters for Сustom Fields of relations
- Visual Reports: possibility to change fields order in axis
- Visual Reports: project entity can be selected as source for historical reports
- Visual Reports: browsing reports data is now possible on dashboards
- Visual Reports: annotations and filters are exported now along with other setup data when cloning report
- Inner Lists: Fixed a case where 'Add & Open' would not work in One-by-One mode
- It is now possible to create Requesters even if your default process has the Service Desk practice disabled
- Max comment length has been increased for the TFS plugin
- Values for Custom Fields will be saved (or removed) when an entity's Project undergoes a Process change depending on the Custom Fields settings in the new Process
- Fixed layout issues in Firefox when performing inline edits to Lists
- Fixed the layout of Team icons on the search results form
- Fixed: Webhook filters would not detect the event 'custom field value is changed' when both the filter and the custom field label contain the word 'Team'
- Fixed a problem where refreshing a Favorite view would cause the left menu to be scrolled down to the "All Views" section upon updating
- If you refresh the page while on a view that lays in a folder, the page will reload with that folder expanded in the left menu
- Entity drag-n-drop on Boards with Customs Fields as lanes will no longer fail when the entity also contains a System Custom Field
- Links in the 'My Recent' menu will no longer break
- Comparisons of two integers vs. float numbers will now work in Visual Encoding filters
- Inline edits for Date custom fields will no longer require an extra click
- Invalid licenses will no longer be saved during failed automatic updates
- Initial LastStateChangedDate is no longer copied when copying an entity to another Project
- Fixed: Import cannot create entities when there is no Project column in the CSV file, and just one Project selected in the Projects/Teams selector
- Fixed: POP email plugin would not create a Request after recreating a deleted profile if a message was sent by the deleted requester
- Feature and User Story views: Fixed incorrect breadcrumbs when opening newly added entities from the Success popup
- Fixed a case where prioritizing entities on Lists via drag-n-drop would result in the entity being placed at the beginning of the List
- Fixed: Comet does not update newly assigned entities in Inner Lists
- Fixed: After splitting a User Story, the name of the new story would be shown on Burn Downs (instead of the original name)
We tend to believe that every new feature is a good and valuable addition to a product. Quite often, it can be hard to not implement a feature, especially when you’re constantly hearing good ideas for new features every week.
The problem is that every new feature adds debt or creates a placeholder for future debt. You deliver more and more features, accumulating more and more debt. Most people don’t know how to work with debts. I don’t. Everyone knows about technical debt, but there are few more types of debt in software development:
- Functional debt. The needs of users are changing, but the system forces them to follow old flows, and doesn’t cover new cases.
- UI debt. Over time, the user interface can lose consistency and coherency, making the system harder to learn and understand
- Quality debt. Bugs are ignored, the system shows unpredictable behavior, experiences errors, crashes
- Technical debt. Architecture and code quality slows down development.
Any new feature in a product may become a source of all these kinds of debt.
|Functional: Feature solves some problem. The problem’s definition may slightly change in the future, so feature functionality must adapt.||All teams estimated work in hours, but then estimation in abstract points became popular. This new need demands changes in a product to support points as an estimation unit.|
|UI: A new feature quite often introduces new patterns and new UI elements.||Designer decides to add new type of lookup field for some feature. This lookup is used in a single place and makes the whole UI less consistent.|
|Quality: A new feature almost inevitably adds new bugs. In complex systems, bugs may affect many other features.||Live Update functionality affects many areas of a system. Bugs in unexpected places will follow.|
|Technical: Technical implementation of a new feature is almost always not ideal. It may cause existing system modifications that are not optimal, and side effects may be severe in the worst cases.||Under time pressure, you implemented a quick solution for UI extensions via Mashups. It does provide great flexibility, but is very fragile. Any change in HTML or CSS can break some extensions. With time, many mashups are created and changes of this mechanism will be hard.|
The image below shows several features in a product. Every feature adds some debts. In reality, it is extremely hard to add a feature with zero current and future debt.
Every Feature needs maintenance: functional, UI, quality, technical, documentation, localization. What if you have 100 features in a product? What about 1000? Can your software read emails already?
New Feature vs. Debt Payment
When should you add a new feature, and when should you pay back some debts? Let’s check the product lifecycle. Imagine you are running a very young startup. You don’t care about debts at this stage. You care about market expansion, new features, and growth. Now imagine the product is dying, it is too late to focus on debts, it’s over.
It seems the right time to focus on debts is when a product has proven its success on the market and is about to enter the “mature” phase. For a typical SaaS B2B product, this may be after 4-8 years. The chart above is valid for our SaaS product, Targetprocess. In my opinion, we started to focus on debts about 2-3 years late. We're finally coming over the hill, but it will take some more time to re-energize development.
Ideally, some part of your resources should be dedicated to debt payment at all times, but after 6-8 years it may even be a good idea to have a “Debt Return Year” or something. At this point, development speed decreases due to technical problems: UI consistency degrades, many features are outdated, bugs and performance issues annoy customers.
Moreover, you’ve accumulated enough customer feedback and now understand your domain much better. Mistakes you made and new opportunities became more clear. You need an ultimate clean-up to prepare a launching pad for a powerful push.
It is extremely hard to slow down and clean up the mess in a product. You are always afraid to lose market share and functional edge. I don’t want to be extreme here, just want you to think about every new feature you add from a debt perspective.
What to do?
There are several obvious consequences.
- Build small systems. If you need a large system, build several small composable systems.
- Less features -> less debts. Someone asks for a new feature? Default answer is “No”.
- Modularization is desired, since you can re-write modules to pay back debts and reduce side-effects. This means you can have more features in a modular system with the same level of debt as in a non-modular system.
- Remove rarely used features. When you remove a feature, you remove all related debts.
I want to finalize my post with a quote:
One thing that UNIX does not need is more features. It is successful in part because it has a small number of good ideas that work well together. Merely adding features does not make it easier for users to do things it just makes the manual thicker. The right solution in the right place is always more effective than haphazard hacking. — Rob Pike & Brian W. Kernighan