I used to do this all the time, but only now do I realise that someone has come up with something to describe it.
This can also be used to hack productivity - making a task seem larger than it actually is, and allowing more time to solve related technical debt by slowing down the rate of visible stakeholder deliverables, but giving just enough carrot to keep their attention. If you introduce the UI quickly but continuously ask for more time to solve the related back-end issues, the stakeholders quickly become frustrated.
The only problem is see if this is “tested” in production is having features that aren’t yet fully ready either form a technical or business perspective and relying on “security through obscurity” to prevent them from being used.
Say you are adding new features those might be exposed in a API prior to have the UI components that facilitate the user interaction directly this isn’t enough to prevent the user from accessing them if there are no additional controls on the backend.
Even worse I would bet good money that for web applications many teams would add UI components and use the “hidden” attribute as a keystone and even if they don’t add any direct UI elements they quite likely to add the JavaScript functions that facilitate those before exposing their trigger in the UI.
Let’s say a user notices that submit order POST requests now have another field “rush_order=false” what happens when it’s set to true?
Sure you can say well the businesses logic would handle this but then you need to make your business logic “aware” of this type of a development which means the keystone isn’t the UI anymore.
This type of development can expose you to various business, legal and security risks if there aren’t excellent controls behind it.
Odds are that very few people would notice it (the "obscurity" part).
If it's a requirement that such features absolutely cannot be invoke by end users in advance of release, it seems like you could always use access control or feature toggles in front of the new backend API. It's important to be aware of such a requirement, but I don't think the fact that some use cases have this requirement gets in the way of "Keystone Interface" as a concept.
For systems in which there is no meaningful way to distinguish users (or say, non-returning customers), these concerns are certainly worth addressing.
Consider, however, cases where the company has long term relationships with customers; say, industries where real customer support is in place. In these cases, an infrastructure for “feature toggles” is extremely helpful, because you can turn on the feature for specific customers (or developers for testing!), or certain segments of customers (e.g. early access customers). In such an infrastructure, there is no “security through obscurity”; you’re authorizing transactions on the backend (based on whether specific users are allowed to use the feature), and merely enabling the UI on the front end based on user whitelists.
Incidentally, once this is in place it’s just another half step to implement phased releases, or A/B testing. Makes rolling back easy too.
Hide the API away too? You don't need to add another field to an existing API while in development, use a different endpoint altogether, to obscure the fact that it even exists. Then, part of the "keystone" can be merging it with the existing API.
This is very specific to your example, but I guess my point is it is almost always possible to design your in-progress state in a way such that new features are obscured.
These are possible problems, but they are unique to this pattern. It's worth being aware of these risk of for sure, but they all have may have mitigations:
- The app may be internal
- The API maybe gated by as API gateway, and the new APIs exposed at a later time.
- APIs should always be coded to have security in depth, it should not matter if the UI is enabled or not.
It's not about delivering changes that are not fully ready to be in production. It's about breaking down a larger change, and delivering it in chunks, as and when each one is fully ready.
There's another problem I run into with this approach, beyond what he describes: It can lead to an outsize amount of rework, because it maximizes the delay before you can start getting feedback from UX or any sort of exploratory or ad-hoc testing.
I remain a bigger fan of the feature flags approach. Even if it's a really nasty redesign and you have to copy/paste an entire view so that you can hack on it in the background and have just a coarse-grained switch to switch between the existing version of the view and the WIP, that's fine, I'd rather have a temporary code freeze on the old version of the view (so you don't accidentally stomp bugfixes or tweaks when switching to the new) than have a project that's big enough it can't be fit into a single sprint get stuck with an outsize risk of nasty surprises late in its development lifecycle.
This is all well and good when dealing with optional features/functionality. But 'required' fields present a challenge.
Such as adding a required field to a form, or updating some process with an additional step. If the UI is added last, but the backend logic is ready and available before the time in production, this would suggest that your backend is either using dummy values temporarily or using additional logic to work around the release delay. In either case, this means:
- cleaning up said extra processing/dummy value logic when deploying said feature for real (potentially introducing bugs during this step);
- requires reverting data storage in the event of dummy input being used where such data needs to be persisted (I'm assuming the backend has been updated already to cater for the required fields since the changes are already in production); and
- other (backend) systems that feed from the other end of the API that now depend on such a field being set, now either need to treat the field as optional and at some later stage add any validation, etc, -or- needs to be scrubbed of such dummy data as well (not always possible).
Seems that the answer in such cases is that enabling the option on the UI is not the keystone, but rather the usage of said fields in other APIs or functionality within the backend. But this complicates matters depending on the backend itself as well as the required usage of said required field(s).
So while I can see some value here, I dont think required inputs are as simple or easy to chalk up.
It seems kind of weird that the article doesn't mention feature flags since they solve pretty much the same problem and Fowler first wrote about feature flags as long ago as 2010. Both solutions avoid feature branches. Feature flags create a small amount of tech debt since the code will need to be removed post GA, but allow end to end tests and staged rollouts over a long period of time which the keystone interface does not.
I found the same thing odd too, but in the back of my mind I was thinking that the idea was "have the feature flag control only the UI; all else is live from the get go and run through CI etc".
The idea of the feature flag could be expanded too, so that if "off" it generated some dummy data while when "on" had the data come from the now-visible UI field.
16 comments
[ 2.3 ms ] story [ 51.6 ms ] threadhttps://en.wikipedia.org/wiki/Cornerstone
This can also be used to hack productivity - making a task seem larger than it actually is, and allowing more time to solve related technical debt by slowing down the rate of visible stakeholder deliverables, but giving just enough carrot to keep their attention. If you introduce the UI quickly but continuously ask for more time to solve the related back-end issues, the stakeholders quickly become frustrated.
Say you are adding new features those might be exposed in a API prior to have the UI components that facilitate the user interaction directly this isn’t enough to prevent the user from accessing them if there are no additional controls on the backend.
Even worse I would bet good money that for web applications many teams would add UI components and use the “hidden” attribute as a keystone and even if they don’t add any direct UI elements they quite likely to add the JavaScript functions that facilitate those before exposing their trigger in the UI.
Let’s say a user notices that submit order POST requests now have another field “rush_order=false” what happens when it’s set to true?
Sure you can say well the businesses logic would handle this but then you need to make your business logic “aware” of this type of a development which means the keystone isn’t the UI anymore.
This type of development can expose you to various business, legal and security risks if there aren’t excellent controls behind it.
If it's a requirement that such features absolutely cannot be invoke by end users in advance of release, it seems like you could always use access control or feature toggles in front of the new backend API. It's important to be aware of such a requirement, but I don't think the fact that some use cases have this requirement gets in the way of "Keystone Interface" as a concept.
Consider, however, cases where the company has long term relationships with customers; say, industries where real customer support is in place. In these cases, an infrastructure for “feature toggles” is extremely helpful, because you can turn on the feature for specific customers (or developers for testing!), or certain segments of customers (e.g. early access customers). In such an infrastructure, there is no “security through obscurity”; you’re authorizing transactions on the backend (based on whether specific users are allowed to use the feature), and merely enabling the UI on the front end based on user whitelists.
Incidentally, once this is in place it’s just another half step to implement phased releases, or A/B testing. Makes rolling back easy too.
This is very specific to your example, but I guess my point is it is almost always possible to design your in-progress state in a way such that new features are obscured.
It's not about delivering changes that are not fully ready to be in production. It's about breaking down a larger change, and delivering it in chunks, as and when each one is fully ready.
I remain a bigger fan of the feature flags approach. Even if it's a really nasty redesign and you have to copy/paste an entire view so that you can hack on it in the background and have just a coarse-grained switch to switch between the existing version of the view and the WIP, that's fine, I'd rather have a temporary code freeze on the old version of the view (so you don't accidentally stomp bugfixes or tweaks when switching to the new) than have a project that's big enough it can't be fit into a single sprint get stuck with an outsize risk of nasty surprises late in its development lifecycle.
Seems that the answer in such cases is that enabling the option on the UI is not the keystone, but rather the usage of said fields in other APIs or functionality within the backend. But this complicates matters depending on the backend itself as well as the required usage of said required field(s).
So while I can see some value here, I dont think required inputs are as simple or easy to chalk up.
The idea of the feature flag could be expanded too, so that if "off" it generated some dummy data while when "on" had the data come from the now-visible UI field.
>That said, there are cases when the UI can't be packaged into a simple keystone. When that's the case then it's time to use Feature Toggles.