Confident React App – Part 5

Here we go again! The “Confident React App” series of posts is finally back after a long period away. You can follow from the start.

From the feature specs – defined in the 1st post of the series – we can observe some important information regarding interactions:

  1. list item selection is toggled when clicked.
  2. the list group works with a single selection of list items.

The second point was not explicit from the specs (and it was intentional so that you could comment on it. Did you notice it?) but we discovered it after some (imaginary) team discussion (backlog grooming, pre-iteration meeting, etc). The team must extensively communicate verbally and written in preparation for the implementation. Many questions arise when the code gets written, especially in the early stages of development. Effective communication is key!

With that in the clear, it’s time to start coding the user interaction of our app.

Oh, behave…

We’re introducing a new component which whole’s responsibility is to handle user interactions and state management: <SingleSelectionListGroup>.

We’ve “transformed” the component’s specification into tests:

// src/components/listGroup.spec.js
// @flow
describe("<SingleSelectionListGroup />", () => {
  it('renders according to specification', () => {});

  describe('when an item is clicked', () => {
    describe('and it is NOT selected', () => {
      it('selects the clicked item', () => {});
      it('deselects any other selected item - single selection', () => {});
    });
    
    describe('and it IS selected', () => {
      it('deselects the clicked item', () => {});
    });

    it('calls the given onChange callback with the current selected index and value', () => {});
  });
});

Now it’s the tricky part: implementing the tests in a way that it’s not coupled with the component’s implementation. 

This is important because we want to be able to refactor our code in ways that better suit the implementation needs without having to modify any of its tests. Attention: if the public API changes, that’s not a refactor! Code refactoring is the process of restructuring existing computer code without changing its external behavior.

You may ask yourself, “What is knowing implementation details?”. If the test code looks for an internal id or CSS class, is it an implementation detail? How about looking for a dependent component? Maybe a function from a 3rd party library? If the test knows one private implementation detail, does it mean that it can use any other private implementation detail as well?

To be honest, I don’t have a definitive answer to this dilemma. There are as many answers as there are development teams out there. And there’s no correct answer, only trade-offs. Mine, which gives me confidence in my code, is as follows.

We want to test the functionality of <SingleSelectionListGroup> component and we know that it must render according to Bootstrap’s style, therefore, it will use <ListGroup> and <ListGroupItem>. But the rendering part is just a detail for the new component. It doesn’t care about HTML tags or CSS classes. We just need to test that the render components are used correctly to represent the state and behavior.

Let’s do a quick thought exercise. Imagine that we want to know as little as possible about the rendering details. One way to achieve this is to incorporate the “end-user point of view”. This means writing tests that rely only on the artifacts that end up in the user’s browser/client like text labels and markup. We could test a bunch of features with these artifacts since most of them are possible to know or mock in the test.

There’s a particular caveat in the list item selection case. In order to test it, it is required to look for the active CSS class. But this class is a rendering detail that is the responsibility of the <ListGroupItem> component. Putting it in another way, the tests would know the details of the details.

Some teams argue that “the tests don’t care how active CSS class got rendered as long as it’s there.” And that works too. The main disadvantage is that if <ListGroupItem> changes class name from active to selected, <SingleSelectionListGroupItem> tests would fail for no reason. It’s a change totally unrelated to the component being tested so the tests should not break.

To me, the approach that gives the most confidence is testing that <SingleSelectionListGroup> uses <ListGroup> and <ListGroupItem> correctly, passing the right props. Yes, the test will know some implementation details but it won’t know the details of its internal components. This approach also protects <SingleSelectionListGroup>‘s tests from any changes internal to <ListGroup>and <ListGroupItem>.

More on this topic later. Here’s a test implementation that follows our guidelines. Red:

// src/components/listGroup.spec.js
describe("<SingleSelectionListGroup />", () => {
  it("renders according to specification", () => {
    const wrapper = shallow(
      <SingleSelectionListGroup>
        <ListGroupItem>Item 1</ListGroupItem>
        <ListGroupItem>Item 2</ListGroupItem>
      </SingleSelectionListGroup>
    );

    const listGroup = wrapper.find(ListGroup);
    expect(listGroup).toExist();
    expect(listGroup.find(ListGroupItem)).toHaveLength(2)
  });

  describe("and when an item is clicked", () => {
    describe("and it is NOT selected", () => {
      it("selects the clicked item", () => {
        const wrapper = shallow(
          <SingleSelectionListGroup>
            <ListGroupItem>Item 1</ListGroupItem>
            <ListGroupItem>Item 2</ListGroupItem>
          </SingleSelectionListGroup>
        );

        wrapper.find(ListGroupItem).first().simulate("click");

        expect(
          wrapper.find(ListGroupItem).first()
        ).toHaveProp("active", true);
      });

      it("deselects any other selected item - single selection", () => {
        const wrapper = shallow(
          <SingleSelectionListGroup>
            <ListGroupItem active>Item 1</ListGroupItem>
            <ListGroupItem>Item 2</ListGroupItem>
          </SingleSelectionListGroup>
        );

        expect(
          wrapper.find(ListGroupItem).first()
        ).toHaveProp("active", true);

        wrapper.find(ListGroupItem).last().simulate("click");

        expect(
          wrapper.find(ListGroupItem).first()
        ).toHaveProp("active", false);

        expect(
          wrapper.find(ListGroupItem).last()
        ).toHaveProp("active", true);
      });
    });

    describe("and it IS selected", () => {
      it("deselects the clicked item", () => {
        const wrapper = shallow(
          <SingleSelectionListGroup>
            <ListGroupItem>Item 1</ListGroupItem>
            <ListGroupItem active>Item 2</ListGroupItem>
          </SingleSelectionListGroup>
        );

        expect(
          wrapper.find(ListGroupItem).last()
        ).toHaveProp("active", true);

        wrapper.find(ListGroupItem).last().simulate("click");

        expect(
          wrapper.find(ListGroupItem).last()
        ).toHaveProp("active", false);

        expect(
          wrapper.find(ListGroupItem).first()
        ).toHaveProp("active", false);
      });
    });

    it("calls the given onChange callback with the current selected index and value", () => {
      const changeSpy = jest.fn();
      const wrapper = shallow(
        <SingleSelectionListGroup onChange={changeSpy}>
          <ListGroupItem>Item 1</ListGroupItem>
          <ListGroupItem>Item 2</ListGroupItem>
        </SingleSelectionListGroup>
      );

      wrapper.find(ListGroupItem).first().simulate("click");

      expect(changeSpy).toHaveBeenCalledWith({
        index: 0,
        value: "Item 1",
      });

      wrapper.find(ListGroupItem).first().simulate("click");

      expect(changeSpy).toHaveBeenCalledWith({
        index: -1,
        value: null,
      });
    });
  });
});

Notice how the test above never looks for HTML specific details like tags or CSS classes. Those details are for the render components. The new tests only care about what the component really is supposed to do: handle the selection, user interactions, and use the propper render components correctly.

Also notice that the tests only used shallow rendering! That’s the utility tool for isolating the component rendering. This forces the implementation to be very flat which is fine for the current needs. Granted, if the component structure was more complex we would need to use Enzyme’s dive() as well in the tests which are also implementation details.

Now go ahead and make all tests turn green. It’s a pretty cool challenge. You can check my solution on GitHub. Don’t forget to add a new Storybook story with the new component to see it in action.

This is it for today’s entry! I hope the confidence in your code has increased a little bit more with my explanations.

Until next time when, hopefully, this series will end.
Cheers!

Prefix Sums – Alternative explanation to Codility’s

Intro

Hello there fellow coder!

This is my explanation of “Prefix Sums” a powerful and versatile algorithm technique.
It can be used for optimizations, parallelization or enabling other algorithms that are essential for all kinds of complex problems.
So it’s a very useful concept to understand, to know where and how to use it. For this post you better be familiar with Big O notation  as I use it to talk about time complexity.

My other motivation was Codility’s material on the subject and how confusing it is. Hopefully my explanation will be clearer than theirs. My code examples are all in JavaScript so you can test it right in your browser.

The concept

Trust me, it’s much easier than it sounds: given a list of numbers A, create a new list P of numbers on which each element is the sum of all the numbers from A prior to its index.

If you are a visual person, this is what it is (A is input and P is the output):

Prefix Sum - P of A
A diagram showing how the Prefix Sum algorithm technique works. P[1] = P[0] + A[1] = 2 + 3 = 5.
If you are a mathematical person, this is what it is:
 Given A = [a0, a1, a2, ... , an-1], of size n > 0
Prefix Sums is
 P = [a0, (a0 + a1), (a0+a1+a2), ... , (a0+a1+ ... + an-1)] 
Or in other words:
P[x] = P[x-1] + A[x]

Like I said, easy huh?

A JavaScript Implementation

There are many ways of implementing this technique but I like this one because is quite readable:
https://gist.github.com/williamrjribeiro/4ea30eb3a942c883fde1068500c6b0cb

As you can see, its time complexity is linear, O(n). Now that the concept is clear, let’s use it.

Simple Example

Imagine that you have to calculate many many times the sum of parts of an array of numbers. It could be for displaying a heat map or the average stock price. Our example just calculates the sum of all sub-arrays/slices of 5 elements from an initial big array.

The most straight forward way to do it is by repeatedly do the iterative sum as many time as needed. Maybe like so:
https://gist.github.com/williamrjribeiro/c8ae00cd550374e5dc7d59ffddae66af
The function sumArrayLinear(A, start, end) from the previous Gist can be represented as:
sumArrayLinear(A,x,y): Ax + Ax+1 + ... Ay-1 + Ay
And we can apply it like so:
sumArrayLinear([2,3,7,5],1,3): A1 + A2 + A3 = 3 + 7 + 5 = 15
The time complexity of our example is O(n x m). Which is not bad.

But now you have another tool available for your disposal: Prefix Sums.

Let’s put it to use.
We calculate the Prefix Sums array with the numbers array. Then we define a new function which takes the Prefix Sums array as follows:
sumPrefixSumArray(P,x,y): Py - Px-1
Which basically reads as: The sum of the interval is the sum at the end (y) minus the sum of everything before the start of the interval (x-1). So with just one operation we obtain the result. Its time complexity is constant, O(1). Let’s try with our example.

The Prefix Sum of A = [2,3,7,5] is P = [2,5,12,17] .
sumPrefixSumArray(P,1,3): P3 - P1-1 = 17 - 2 = 15
Which is the same result as before, therefore:
Ax + Ax+1 + ... + Ay-1 + Ay = Py - Px-1

We can rewrite our code to use our new function:
https://gist.github.com/williamrjribeiro/f919c550ffa78248af3de93522853ccb

The total time complexity is O(n) + m x O(1) which is simply O(n+m). And that’s pretty good! Of course, it all depends on the values of m & n. For our example, the first approach needs roughly 140 operations to obtain the resulting array while the seconds needs only 61.

Fin

There you have it!
The Prefix Sums technique for all sorts of other more complex problems. A powerful simple idea.
Was I clear? Spotted any problems or bugs? Do you know other examples where Prefix Sums can be used? Speak up on the comments bellow.

Cheers!

Memoir: Send your Remember Notes to Microsoft OneNote™

Hello everybody,

Great news for us, BB10 loyal users: independent app development is not dead yet!

I have created a very simple app but which I think it’s really neat. It’s called “Memoir” and it is immensely useful to me and hopefully it will be for you too. It’s not free because I put a lot of effort in it and I value my time and effort. So, if you want more apps for BB10, please support your favorite independent dev by buying and reviewing our apps. With enough paying costumers it will enable me to continue doing what I like: cool and useful BB10 apps!

I’m giving my best with this app but even so there will be bugs. Actually, this is an unofficial BETA release. It works just fine in most cases but there are some edge cases that are not fully covered so … don’t push it too much. Or push it and break it but, please, report it to me so I can fix it.

This first version has only the core features but if reception is good, I’m planing to add more cool stuff. You can even ask for what would you like to see it doing. Just send me an email or a message in Twitter.

Grab your copy on BlackBerry World while it’s on LAUNCH SALE for 50% Off the regular price! Promo will end when I release the next version so hurry up before I release it.

Please share it with your friends and spread the word.
Cheers!

Get It At BlackBerry World

MEMOIR – Send your Remember Notes to Microsoft’s OneNote™

Memoir* [mem-wahr, -wawr]; noun;
1. A record of events written by a person having intimate knowledge of them and based on personal observation.
2. Usually, memoirs. An account of one’s personal life and experiences; autobiography.
The published record of the proceedings of a group or organization, as of a learned society.
3. A biography or biographical sketch.
Even tough BlackBerry provides a great note taking app, Remember, it has a big shortcoming: it’s impossible to backup its data or export it, not even with BlackBerry Link. This means that you have to manually copy and paste all data somewhere safe.

Don’t let your precious memories go to waste. With the Memoir app you can secure your memories in to the cloud with just one tap.

HOW WE DO IT? 
All the Notes and Folders stored on BB10’s Remember app can be easily uploaded to Microsoft™’s excellent OneNote™ note taking app/service. A Notebook named “BB10 Notes by Memoir” is created in your OneNote™/OneDrive™ account. Every Note Folder from Remember is a Section of the notebook. Every Note from Remember is a Page on OneNote™.

MICROSOFT ONENOTE™
It’s a free cross-platform app and service. It’s has many advanced features and is deeply integrated with the latest version of Windows™ and their cloud storage service OneDrive™. It’s a perfect place for preserving your precious notes and enabling multiple ways of accessing it. To use Memoir you’ll need to have a Microsoft™ account.

MAIN FEATURES:
– Support for Remember Notes and Folders.
– Attachments: images, audio, pdf, ppt, doc, xls e etc.
– Upload All with 1-Tap.
– Fast Native/Cascades interface. Very simple and effective.
– Secure integration with Microsoft™ Account. A Microsoft™ account is required. OneNote™ permissions must be granted.
– One-way synchronization. Only changes from Remember app are detected and uploaded.
– Support for OS 10.3.0 and higher.

PLANNED FEATURES:
– Integration with other cloud services. Google™ or EverNote™? You choose!
– Support for Tasks.
– Two-way synchronization. Changes to Notes made from OneNote™’s apps are downloaded to the device and appear on Remember app.
– Give OneNote™ permission only once. Permission is only granted for 1 hour in current version.
– Support for OS 10.2.1
– Other languages. Volunteer native speakers are welcome!
– Change OneNote™ Section by changing Notes Folder
– Change OneNote™ Master Notebook name

Ask for what feature you want most on the app review or by email: [email protected]

If you have any issues please contact our support email or reach me on Twitter.

Thanks for your time!

Here are some screenshots of the running on a Z10 and Q10:

Why bother with BB10 development?

Yup, call me stubborn. What can I say besides that I really like the underdog, the odd, the beaten up and failed. My last post was about a project that I did in Flash and now a new post about a BlackBerry 10 app. Those are two technologies that I have very good experience and that I have a lot of fun using so on my free time I can’t help my self. What do I gain from it? What motivates me?

There’s something special about the underdogs: their despair to succeed. Much like the old saying about “Never fight a cornered animal for it will give a hell of a fight for it’s life”. A company that is in trouble will try their best to succeed – or at least they should. And what tech companies do best? They innovate! They put their best efforts into bringing great technologies hoping that it will win the market’s heart and save them. I find this situation greatly interesting so I watch closely their fight for life.

BlackBerry was – well, still is – cornered so they tried their best and as a result we have: BB10 OS and Blend on the software side and the Passport representing the hardware. Both extremely innovative products on their own merits but unfortunately they didn’t save the company. When innovation doesn’t work, companies put a fresh coat of paint on their best selling product and try to sell the hell out of it – the Classic – or they copy their competitors – the Priv with Android. Nowadays I don’t watch BlackBerry anymore… but let’s move on.

I do learn a lot about the problems at hand, like using the OneNote REST API, how to make multi-threaded programs, memory management, development of User Interface and Experience, localization, so on and so forth. These are actually the concepts that are the hardest to learn and master but the ones that I can pretty much take with me and use wherever needed. Just the implementation details will be different.

There’s a lot of value in mastering a programming language, framework or another tool. Many times I had to help a fellow senior developer on my team to deal with JavaScript craziness. Oh so many bugs on which the fix was some insane language detail that they didn’t know. I coined a phrase that I used multiple times on my code reviews: “JavaScript is a bitch”. So definitely yes, my expertise with Flash and Cascades – BlackBerry’s own native framework for app development based on Qt – won’t get me that broad advantage on the market place but there are still COBOL experts being hired right?

Another thing that I got used to was people frequently asking me, with an incredulous face, “Why BlackBerry?!”. There’s a strong reason and it’s quite reasonable. BlackBerry World has a little bit more than 370K apps available for download. iTunes App Store has more than 1.500K! That’s 4x times more apps, 4x more competitors. Barely any room for indie devs. There’s also lack of official support from popular services like Uber and Telegram. On BlackBerry World there’s only one very good paid app for each, a couple of odd balls.

These points show two clear things: as a costumer it sucks to have a BB10 phone because you’ll miss a lot of apps, a problem that for many experts was the crux of BlackBerry’s demise. As an independent developer it’s a gold mine! It’s all about competition and marketing power. With the same amount of effort I can have a very good compelling Sudoku game or Telegram app on BlackBerry 10 without much competition from other players. How can one indie dev compete with hundreds of other apps available on Apple’s AppStore, of which the best ones are the official ones or created by App Factories with dozens of dedicated professionals? My indie app would univocally end up in the middle of the “noise”, the sea of dead apps full of clones and ad-ware. And no matter how much I polish and improve my app it wouldn’t leave this dreadful app store deadzone. To leave it, the app must be heavily marketed! On forums, podcasts, tech blogs, forums, Twitter, Facebook and any other channel you can think of. But remember, your competitors can afford Super Bowl ads and hire Hollywood movie stars.

What’s for grabs? BlackBerry 10 has sold an estimated 15 million units world wide and shrinking. Apple has a whole f****** lot of millions and growing. The effort so sell 100K on BB10 is quite low and actually reasonable considering that if you have a unique essential app. A person will simply have to buy it from you because they are stuck with you. To sell 100k on the iTunes App Store you’ll have to invest much much more. Wanna be a billionaire? Be a CEO of a startup, get a lot of funding for development and marketing and go for Apple. Wanna be a millionaire, work hard and go for BlackBerry (while it lasts). As an indie dev, BB10 is just more reachable therefore much more motivating. Oh, and you can apply my arguments if you change Apple for Android and BB10 for Windows Phone.

I hope that the answer to my question was clear and if you are smart enough, you won’t bother with BB10. (And will let this small gold mine just for a few silly ones).

Cheers!