Angular RxJS unsubscribe as a feature design

After few hours of thinking and more hours of implementation, I finally proved my idea is workable. I found it be a bit intriguing and so let me share it. Before jumping to the matter at hand, I would like to briefly mention that:

  • I don’t believe in end-2-end testing
  • I prefer unit testing
  • I like to test-drive my code

A few more details can be found here. On top of the above, I dislike using mocks, spies, stubs and other fakes to make testing “easier”. Now don’t get me wrong I do use mocks a bit, but mostly at a boundary (calls to backend, db and such). Let’s be reasonable, if code is a mess and/or legacy or there is a time constraint, options tend to dwindle and if you have to mock, you mock.

Now let’s see about my situation: I have simple app with navigation bar, located at the very top of the screen and top of the component hierarchy. The navigation bar contains search component. Below I have the main space with a router that happily swaps out different main components, depending where you click.

There is no simple way to pass data from the search component to presently displaying main component, unless we use observable, in particular Subject observable. So we have search observable and a main component is subscribed to it. The question is: “how do we test unsubscribe in the main component when we navigate away and the main component is destroyed?”.

After some thinking, I realized that NOT every main component is searchable, in those cases search component can be hidden. The approach has elegance to it, since it will help with testing and at the same time enhance user experience by eliminating confusing search feature that doesn’t seem to do anything when non-searchable main component is displayed.

On the other hand, when main component is searchable, then search component must be displayed so user can search it.

Ok, so how do we go about killing two rabbits with one bullet? We will enhance the search observable so it will count how many subscribers it has. Whenever any main component subscribes or unsubscribes to the search observable, the count will go up or down. Next a bit of elbow grease to wire up search component to hide/show when the count is equals to or less than 1 and we are done.

The whole logic can be tested by checking if the search component is displayed or hidden via jasmine spec, by navigating between main searchable components and main non-searchable components. No mocks, no spies, just elegant, user friendly feature and code design.

sTool Request

Every developer is familiar with Pull Request, however recently I came across another useful practice – “sTool Request”. sTool request is a simple and powerful practice yet some, especially junior developers, hesitate to use it; at least I noticed the behaviour in my team and so it is a good time to talk about it.

Unless your team is practicing pair programming, everyone tends to work alone and often the only time you get to see work of another developer is at Pull Request time. While it is generally a good thing, there are few drawbacks:

  • Effort has been expanded – sunk cost bias has already kicked in
  • Work is completed – physically & physiologically – let’s move on to the next thing
  • Code has settled – mistakes are more expensive to fix
  • In case a bug is discovered at a later point, it is harder to figure from the original developer – rarely anyone remembers details of decision making and code several weeks back.

sTool Request can help remedy those issues to some degree, at the very least it is cheaper to brainstorm/discuss questions, issues and ideas prior to producing code, and/or at any point during the work. So here goes my proposal to a team:

“Got a question or a doubt? Perhaps you want to bounce ideas around? Ask a team member to grab a stool/chair, sit down and help you out. Use the momentum to have a rich conversation and/or debate. Don’t wait for PR (Pull Request), refactor card, or a bug report. We are all on the same team, working together to deliver team’s goal, improve quality and learn new things.”

I would love for people to pair program, but in the absence of the practice, it is useful to invoke “sTool Request”, summon a developer and work things out. There are so many times I though to myself: “if only a developer have asked prior, he wouldn’t have made those mistakes and also learned a ton from the experience”. It is harder to learn retrospectively, it is better to learn in the moment.

You should definitely throw an exception

A while back I decided to make a progressive web-app and for the fun of it, learn a new framework (Angular 7 at the time, 9 now), language (TypeScript) and to top it all off, challenge myself by test driving the entire thing.

Before I dive into our main thought, a little disclaimer: I’m sort of a full-stack developer; meaning my world rotates around developing microservices with Dropwizard + Java 8, a little bit of front-end with Backbone & Marionette + JavaScript and a little of Oracle on DB side. Uninspiring and outdated, stack is my daily existence. Regardless of stack, I do test drive all of my code, I believe it is a good idea and I have been doing it for a while now.

From the very inception, I decided to test drive my app and to do it only with unit tests and depending on your definition, integration tests. After years of writing, re-writing and maintaining end-2-end tests, I figured one thing only: they are a waste of time and money. So my entire app is test driven by jasmine specs, starting at individual components (or a service) and moving onto a combination of components (how they work together) and culminating with the main component which is mostly in charge of testing navigation through out the app.

Now, to test a component in Angular (to the best of my knowledge and understanding) is to test a template and associate code together as one thing (unit of work). This represents a bit of a challenge, mostly associated with manipulation of UI. Effectively you will be doing a lot of query selections, clicking, and sometimes dealing with async and Angular change detection. Since I get to work on my app few hours per week, I tend to forget (sometimes rather quickly) fine details of writing a component test. Like the saying goes: “if you can’t beat them, join them”, so I gave up on constant rehashing and decided to write my own test helper, which is easy to use and doesn’t need much to remember. For example, find an element with the placeholder value of “name”.

In addition to all of the above, jasmine errors tend to be verbose and not very user friendly. For example if you are trying to query select all elements, which don’t exist (but you assumed they did) and then call a method on a particular one, you will be met with off-putting exception “undefined is not an object”.

TypeError: undefined is not an object (evaluating 'this.findElementsByPlaceholder(placeholder)[0]') in http://localhost:9876/karma_webpack/main.js (line 3909)

I believe we can do better than that. We can wrap “query select all” calls in your own method, check length and if there are no elements then simply throw an error with explanation. For example:

Error: Could not find a placeholder: name in either of tags: placeholder,ng-reflect-placeholder in http://localhost:9876/karma_webpack/main.js (line 3906)

By doing so, you effectively eliminate confusion and save yourself some time (at least I do). So go out there and throw some well-explained exceptions, so you don’t have to guess which object is undefined and why.

Cheerz.

Multiselect dropdown

Today in the morning I spend couple of hours trying to implement dropdown with filter and “valid only” entry. I started my endeavor with ng-bootstrap dropdown (since I’m working on Angular app), quickly realizing that it will not work since there is no filter option. Next I figured that a typeahead will fit much much better.

Everything worked out very well except for one big caveat: the typeahead does not clear “<input>” field when entry is not valid (not in the list of options). After monkeying with “onBlur” for about 20 minutes, a sane thought occurred in my head: “What am I doing? Hacking? There must be a straight forward way!”.

Welcome Multi-Select Dropdown

The Multi-Select Dropdown also supports single option:

It looks promising and I’m very happy someone figured it out, however I wonder why doesn’t ng-bootstrap include such a useful component?