My AngularJS Views Are No Longer Based On Assumptions But On Fact

March 22, 2014 — 8 Comments

It used to be that my natural inclination would be to wire my view templates in a manner that made assumptions about the users’ intentions and expectations, based on my understanding of the requirements. This could be seen not only in the way that I named the properties and methods that would be exposed by the controller / view model, but in the way that the view interacted with these properties and methods. Take the following AngularJS view template code as an example:

A tad bit contrived, but what we have here is a button with a label of ‘Get Items From The Server’ that when clicked, should result in some items being retrieved from the server and displayed as a list to the user. If there is a problem retrieving the items, however, then an error message in a confirmation dialogue box would then overlay the screen, notifying the user of the problem. Notice how the properties and methods of the model are named. Because I’m assuming that a user that clicks the ‘Get Items From The Server’ button, is attempting to, well, get items from the server, I have called the relevant controller action method, ‘getServerItems()’. Additionally, because I’m assuming that the item list should only be shown when there is at least one item, I’m simply using the expression someModel.items.length > 0 to determine when the list should be displayed. Finally, because I have assumed that if a user clicks the ‘OK’ button in the confirmation dialogue, the user’s intention is essentially to hide the confirmation dialogue box, I’m simply assigning false to the someModel.serverErrorDialogueIsVisible property directly within the template code. This is essentially how I would wire up my views. In essence, my assumptions regarding the users intention would dictate how the view template would interact with the view model and controller.

Overtime, however, as I strived to do things better, I realised that this strategy was failing me in a couple of ways. Firstly the method names almost always ended up not accurately reflecting the functionality that they provided. For example, let’s assume that the controller was coded as follows:

Notice how the getServerItems() method is not only retrieving items from the server, but is also conditionally assigning values to properties on the model that determine whether either the items or an error message is displayed to the user? In other words the getServerItems() method is essentially doing more than just retrieving items from the server. Though this point may seem trivial, to me it was an indicator that something was not quite right with the strategy I was applying. A code smell (if you will).

Now the second way in which the aforementioned strategy was failing me, was that it made the view template more brittle. This is in the sense that as my understanding of the app implementation requirements increased, or if the requirements were changed altogether, the assumptions that I made in my view template would almost always become invalidated. This is even if the change to the requirements was not presentation specific, but only business / domain specific. Ideally, a requirements change that is not presentation specific should not result in the presentation layer needing to be amended. Again, this was an indication to me that something was not quite right somewhere.

For example, let’s say that a change in the requirements mean’t that when the confirmation dialogue ‘OK’ button was clicked, an email had to be sent out to the business (for some reason or the other) in addition to hiding the confirmation dialogue. To achieve this, I would have to now change the view code so that it no longer interacted directly with someModel.serverErrorDialogueIsVisible when the ‘OK’ button was clicked. Instead it would call a method on the controller that would send out an email in addition to hiding the confirmation dialogue. Thus, this change to the requirements that is not presentation specific would have resulted in changes being made to both the presentation template and the controller when it should have only been restricted to the controller. For me, this is not a good thing because it means that I would have to do more work to maintain the app, seeing that a single requirements change can end up affecting more parts of the codebase than it should.

There is also now the issue of deciding what this new method should be called? I could call it hideConfirmationDialoge() but then I would have the same problem as before. The method name would not accurately reflect what it is doing, seeing that it is now also sending out an email. I could call it hideConfirmationDialogeAndSendOutEmail() but this naming convention is now not scalable as it would mean that if another responsibility was added to the method, the name would also have to be changed to reflect it. This means that not only will the view code have to be amended each time, but the name may eventually become just too long to be practical. Eventually, I would just have to settle for a name that I was unhappy with and my attempt to be clever by directly assigning false to someModel.serverErrorDialogueIsVisible would have proven to not be so clever.

The third and final way in which the strategy was failing me was that it required too much brain activity. I found myself constantly trying to decide what to call a method or property, as well as constantly thinking of how to do things in so called ‘clever’ ways, like reusing stuff or assigning values to properties directly when they made sense etc., only to have to change them later on. Not only did all this thinking make the process of wiring up view templates, a slow, and mentally tiring one, it also made having my view specific assumptions later become invalidated each time the requirements changed, hard to bear. It was like watching the valuable time and brain capacity that I invested in good faith, just waste away.

So how did I eventually solve this problem? I stopped making assumptions and just started coding based on the facts that were in front of me. For example, instead of calling the ng-click method of the OK button something like hideConfirmationDialogue(), based on what I assumed was the intended outcome of clicking the button, I would now just call it something like okButtonClicked(), based on the fact of what the user actually did, which was to click the button. Additionally, instead of using the expression someModel.items.length > 0 to determine whether the items should be shown, the expression someModel.showItems would be used, based on the fact of what is happening in the view. As a result, my view code would now become…

This for me solved all of the aforementioned problems. Firstly, because controller hander method names are now just a factually statement of the event that took place, the method is now free to do whatever it needs to do without ever violating the truthfulness of its name. It now just becomes an event handler instead of an action initiator and the smell goes away. Note that this also improves both the readability and maintainability of the code, especially at the controller level. A developer that has to troubleshoot a controller issue that occurs when the ‘OK’ button is clicked, no longer has to load up the view to see how it is interacting with the controller. Instead, by using this naming convention, the developer can just go straight to the controller and look for a method named something like okButtonClicked. Thus, less time and brain capacity is spent trying to find things.

Secondly, this strategy forces each user input interaction to now delegate to its own controller action method instead of sharing methods for the sake of reusability. Similarly all display logic is totally removed from the view template with model properties solely being used to determine, for example, when things are shown or hidden. In other words, instead of using someModel.items.length > 0 to determine whether or not the items should be shown, someModel.showItems will instead be used. The benefit of this is that the view template code no longer needs to change whenever the requirements change in a manner that is not presentation specific. In fact, I have found, that once the view has been wired up in this way, it almost never changes as almost all changes now only happen at the controller and / or domain layer. For example, if the requirements changed to the point that two events that were previously sharing the same handler implementation now each required their own custom implementations, I would not have to make changes to both the view template and the controller. Because each view event already delegated to its own unique controller handler method, only the controller will need to be amended. As a result, maintenance of the codebase becomes easier seeing that changes in the requirements now affect fewer places.

Thirdly, this strategy requires virtually no thinking as everything I need to know in order to formulate property and method names are right there in front of me.  An OK button click handler will simply be called okButtonClicked(). A Try Again button click handler will simple be called tryAgainButtonClicked(). A property that determines whether a service error dialogue will be displayed will simply be called showServiceErrorDialogue. You get the idea. Wiring up the view now becomes a quick and easy task that doesn’t wear out my brain. Because there is now no need to think about the users intention when interacting with the view, no thinking is required on my part to wire up the view. At least not the type of thinking that stresses the brain. I now no longer even need to be bothered with the business / domain requirements (a task that requires thinking) when wiring up the view. It’s only when I start working with the controller onwards that I start focussing on the business / domain requirements and this makes sense to me in that the view template should not be concerned with business / domain requirements. It should dumb, with its only concern being to reflect the state of its designated view model (in my humble opinion). I have realised that if I’m thinking about the users intentions, I’m inadvertently thinking about business / domain requirements. As a result, they creep into the view, rendering it more susceptible to requirements changes that are not presentation specific.

So now my cardinal rule when wiring up my view templates is to never assume anything at the view template level. Instead, my only concern is now with the view specific facts that are in front of me. To summarise, this essentially means that:

  1. Where handling user initiated events are concerned, I now no longer handle the event with logic that is directly in the view template. Instead, I now always delegate to a controller handler method. In other words, I would do  ng-click="dialogueOkButtonClicked()" instead of ng-click="someModel.serverErrorDialogueIsVisible=false". Doing so not only makes the view template code cleaner and more readable to me, but it also makes it less brittle. I have found that having even the minutest of logic means that assumptions are being made that will most likely be proven to be wrong later on when either the requirements change or are better understood. For me, it’s just not worth the mental effort, as well as the extra maintenance work required to amend the view template later on.

  2. I now name controller handler methods in a manner that states the facts regarding the event that took place. For example, I would use okButtonClicked() instead of hideConfirmationDialogue(). Not only does it ensure that the method implementation does not violate its name, but it’s also easy to formulate as no thinking is required on my part to do so. Furthermore, it later makes maintenance easier as I can then use the naming convention to quickly find stuff.

  3. Where view logic / state is concerned, I now always bind to view model properties that represent the state of the view. No longer do I allow even the minutest of view logic. For example, I would use ng-show="model.showItems" instead of ng-show="model.items.length > 0".  Again, not only does this make the view template code more readable to me, it also makes the view template code less brittle for the same reasons that embedding event handler logic directly into templates is not recommended.

  4. I now name view model properties in a manner that best represents the view state instead of using assumptions to formulate model property names. For example, I won’t do ng-show=“someModel.itemsExists” because I feel confident that the items should only be shown if they exist. Such an assumption is brittle and may be proven wrong in the future. Instead I would do ng-show=“someModel.showItems” and let the controller decide what this value should be. I now leave all reasoning to the controller. Again, I have found that doing so significantly reduces the amount of times that the view template has to change as a result of changing requirements. Such names are also much easier for me to formulate.

So there you have it. This is more or less the strategy that I now use when wiring up my view templates. It has helped me to quickly churn out views that are in my opinion, very clean, readable and resilient in the face of changing requirements. Note that I in no way state that this is “The Way”. I simply state that this is just what I now do. I share it simply because it is the sort of thing I wished was out there for my consideration when I was starting out. As always, please feel free to share any thoughts or insights that you may have.

TwitterFacebookGoogle+LinkedInDiggRedditStumbleUponEmail

Ifeanyi Isitor

Posts Twitter Google+

I'm a web application developer / independent contractor, currently residing in London.
  • Pingback: My AngularJS Views Are No Longer Based On Assum...

  • Pingback: My AngularJS Views Are No Longer Based On Assumptions But On Fact | IFY I/O | angular.org.il

  • bhattacharyyapulak

    Good to read!!!!!!!

    • ifeanyiisitor

      Cheers

  • Darrell Gallion

    I agree with your observations.

    The web apps I write control machines, imagine control panels.
    I’ve moved as much logic as possible to the embedded devices.
    Through events arriving on a websocket the embedded device can control some aspects of the display.

    Similar to your concerns, I limit the logic in the web app.
    For example, a developer asked me to round the display to two decimal places.
    Push back, do it in the c++ app before sending me the event.
    Otherwise the web app is filled with special cases.

    • ifeanyiisitor

      This sounds interesting. I have actually never developed this sort of app. So the embedded devices act as sort of the control layer with the web app being the view layer?… and the controller layer instructs the view layer with events?

  • Jeremy Likness

    It’s a good read, but I’d add some to it. I even think calling it “OKButtonClicked” is perhaps too much information. One of the benefits of having a declarative UI is the ability to shift things around for the design without necessarily breaking the presentation and underlying logic. For example, right now you have an OK button. Great! But what if the designer decides they want that to be a link, or even some other implicit call? Then it’s no longer relevant and subject to refactoring. However, regardless of the button or link or whatever, there is a behavior that is taking place. In this case, it’s a confirmation that things are OK. So naming the method confirm() means you can bind it to an OK button, a link, the ENTER key, or just about anything else you want.

    To further that notion, I love what you talk about with the items and the idea of showing or hiding them. A common mistake is to assume how a collection may be portrayed. We might do “listOfItems” in a drop down with a selected Item, but we may just as well use a list box control or other way of representing the list. “Selection” may be the selected item in the drop down or simply a highlighted item in a list.

    Either way this is not disagreeing, only further expanding on your article – to fully appreciate data binding, the declarative UI layer should be able to bind to “ideas” rather than explicit implementations – the idea of confirming the dialog, the idea of representing a list, and the presentation layer should orchestrate the steps that satisfy the idea, i.e. sending an email and closing the box is part of the “confirm” idea rather than the “closedialogandsendemail” idea.

    Thanks!

    • ifeanyiisitor

      Thanks for these points @Jeremy Likness. I like your suggestion to go a step higher and focus on the behaviour with confirm() instead of ‘okButtonClicked()’. This would indeed make the controller more versatile to the view. If I had to reuse the controller with a different view template or the app was to later be re-skinned, the controller would still remain relevant and usable without needing to be amended. As you say, it is indeed an enhancement to what I have suggested, as my suggestion is more focussed on making the view more resilient to changes in the controller. Your suggestion, however, makes the controller more resilient to changes in the view, which is like adding some icing on top of the overall app cake if one can have both.

      One issue I see with binding to ideas such as ‘confirm()’, though, is that the name is now a little too generic. There is now too little information when viewing this method in the context of the controller. In other words, If another developer wired up the template and then handed the app over to complete the implementation of the controller methods, it would not be clear to me what confirm() relates to in the view. I would have to refer back to the view template to see that confirm() is the click handler for the confirmation dialogues ‘ok’ button. Thus, too much contextual information would now be lost when the method is viewed from the controllers perspective and as a result, the maintainability of the app would decrease. No longer would I be able to simply use the naming convention to easily get an idea of the overall context, as well as to know what method I need to work with in the controller (this is important and I will explain why in a moment so so please bear with me). Furthermore, having to mentally jump between the view template and the controller whenever I have to address something in the controller will now be a bit of a brain drain. For me, it tends to be that the more files I have to mentally juggle to get something done, the more mentally draining things becomes.

      A compromise would be to rename it to something like ‘dialogue_confirmed()’ instead of just simply ‘confirm()’. Though it is not as explicit as something like ‘dialogueOkButtonClicked()’ it still allows one to have a better idea of what it relates to than simply ‘confirm()’, while also being generic enough to allow for changes in the view template such as the button being changed to a link and so on. Furthermore, If a ‘Retry’ button was also added to the dialogue, one could call the click handler something like ‘dialogue_retryConfirmed()’, in keeping with the naming strategy.

      Now while this seems to work fairly ok when dealing with a simple confirmation dialogue, it seems to me to not be as easy to apply across the board. If we consider the ‘Get Server Items’ button, for instance, what would be the behaviour that is related to clicking this button? Would it be that a ‘request’ is being made for items similar to how clicking the ‘ok’ button in the dialogue means that a ‘confirmation of things being ok’ is being made? If so, then the click handler would essentially be called something like ‘itemList_retrievalRequested()’ or ‘itemListRetriever_request()’ or ‘itemList_request’ or even simply ‘retrieveItems()’. Again, due to the generic nature of such names, however, I would still have to open up the view to understand that the method is being called in the context of a specific button click. From simply looking at the name of the method in the controller, I cannot deduce enough about the context in which it should be used and as a result, I have to now go back and forth between the view and the controller to understand more about it. This again results in a bit of mental drain as well as decreased maintainability (essentially all the problems I describe in the article).

      Now if the word ‘button’ and maybe even ‘click’ was in there as in ‘itemListRetrievalButtonClicked()’, then it would be plainly obvious what it pertained to. This, as you have mentioned however, would reduce the adaptability of the controller. Maintainability is not really reduced because a name change is simply a refactoring affair that can easily be handled with good refactoring tools. Furthermore, (and this is important), lets say there were two different buttons that should bind to the ‘retrieveItems()’ idea, but clicking one of the buttons causes an activity indicator to be displayed in the view while clicking the other doesn’t cause this to happen, I would essentially have to have an ‘if else’ condition in ‘retrieveItems()’ method to cater for this. Thus, the cohesiveness of the method is now reduced, which in turn will reduce the maintainability of the controller. The only other way to get around this without introducing logic into the view, would be to have two different method calls that each cater for their specific case. Then at that point, how would these two methods be differentiated in their names? Too much thinking for me. For me it is just simple to call it according to what they are in the view.

      You see, the reality that I have found with binding to generic ideas in the view template is that it is the controllers implementation that suffers. It introduces spaghetti in the controllers with many if else blocks to handle edge cases. All the clever reuse that it provides to the view is at the expense of the controllers maintainability. No longer does one action handler have a single logical responsibility. Now if one is to keep the method that represents the idea as clean as possible (i.e., without all the if else spaghetti), then the method will have to cater for the lowest common denominator (so to speak) in terms of its functionality. This in turn would, encourages logic to be added directly to view templates due to these methods being too generic to cater well for every use case. Additional use cases will essentially be supplemented with additional logic being placed directly in the view templates. In this way the views now become less maintainable.

      The question then arises as to which method is more preferable. Do we prefer to have a resilient and tightly fitted views at the expense of ‘building blocks’ adaptability of the controller? or do we prefer to have the sort of building blocks adaptability that binding to ideas provide at the expense of overall app maintainability and view resilience? This to me, essentially depends on who the app is being developed for. In other words, if it’s a widget or component that is being developed to be easily integrated into view templates of apps that belong to third party developers, then it would be more beneficial for them to have generic action handlers that allow for binding to ideas in the building blocks fashion that you describe, so that they can be used in whatever manner that makes sense to third party integrators. In this case, view resilience would not be a desirable feature seeing that view specifics can very different for different third party integrators. Because these third party developers / integrators are essentially the customers, any decreased maintainability that may be introduced as part of facilitating this building blocks feature that is more beneficial to the customer, becomes acceptable.

      If the app being developed is an internal app, however, or a client app with very specific requirements… in other words, an app that is not meant to be integrated as a module into other third party apps, then I would prefer the overall maintainability that I get with the sort of views that I describe in this article. This is more the use case that I was addressing with the article. Virtually all apps that I have developed such as this (i.e., apps that have very specific requirements and are not meant to be used as modules in other apps), have never ended up being needed to be adapted for reuse. Furthermore, by the time the app gets to me, the specs would have been properly fixed, thus meaning that specifics such as whether to use a button instead of a link, would most likely not change much (if at all). As a result, it becomes a bit of a waste to optimise for such ‘building blocks’ adaptability. Additionally, as previously stated, any such change that does happen once in a while can be easily handled with good refactoring tools. What definitely does happen continuously though is that such apps end up needing to be continuously maintained and enhanced. Because of this, I now no longer optimise for generic adaptability over maintainability. Instead I treat having adaptability as more of a feature that the client must explicitly request before I optimise for it. Mind you, that doesn’t mean that I don’t have adaptability in mind at all. I would still make things adaptable where ever they make the most sense, but only once doing so does not hinder maintainability.

      So for me, the difference is similar to the difference in having a tailor made outfit, over an outfit that is designed to be ‘one size fits all’. Each are applicable to different end goals. Tailor made outfits by design are made to fit and look much better on a specific client. Thus, if the outfit is not meant to be sold at mass market, but is instead being requested by a specific client, it would be better to tailor fit the outfit to the exact measurements (specifications) of the client. Doing so would be more pleasing to the client and as a result more beneficial to my longevity as a tailor of that specific client. In other words, it would be easier for me to maintain that client. If mass market distribution is the goal, however, and everyone is the client, then the ‘one size fits all’ is the way to go. This comes, however, at the expense of having the outfit looking great for all seeing that it now has to be maintained for all.

      You can also liken the difference to having a wife over having a many girlfriends. Coupling tightly to one wife is just more maintainable (to me at least) than loosely coupling to many girlfriends. With my wife, we can establish many conventions between us that are very specific to our relationship that make both our lives very easy. Regardless, however, there is a time in ones life where one prefers the loose coupling of many girlfriends over the tight coupling of a wife.

      With all this my point is simply to say that the strategy that will be used has to be determined by factors such as who the client is. For me, it’s not an ‘all or nothing’ situation. I’m very glad that you brought it up though as it forced me to capture my thoughts on this. I’m quite interested to hear any further thoughts you may have on this. Many thanks once again for your comment as it does indeed provide a different dimension to be considered. Cheers.