My comment to a question about unit testing on hacker news

Leave a comment

https://news.ycombinator.com/item?id=15592743#15593821


This is the biggest challenge. What I find works is separating your orchestrations from your data processing.

For example, instead of creating one class that does the network call, and processes the JSON response, break these out.

One class does the network call (keep it extremely thin). Dependency inject stuff in if you want. But view this purely as an orchestration.

if (connectionValid)
json = makeNetworkCall
anotherObject.processJson(json) <- test separately
end

Then, in the other plain old data process class, do you heavy off-by-one edge case testing there.

If the first case, the orchestration, I can write tests like "One make the network call if the connection is valid". But that's all that test would do.

I am at the point now where I actually don't even test that. I assume that is going to work, because it is so simple. That and I generally hate mocking. Way too much coupling. Way too hard to refactor.

Where I do test heavy is on the plain old object side, that has no outside ports or connectors. These are just plain old objects.

I agree with some other comments I have ready here. Mocking is a bitch and I generally don't like it. But it's there if I needed it, so I do use it occasionally.

But it has so many downsides I try not to. Instead I separate the orchestrations from the processing. Unit test the processing (in an integration test sort of way), and try to stick to testing the public APIs of my class, so I am free to change the internals without things breaking.

My 2c. Hope that helps.

Advertisements

JavaScript Recursion #7

Leave a comment

This is how you define a function in ECMAScript6

Screen Shot 2017-10-13 at 7.32.40 AM.png

let is the new var
arrow function is the new way.

And this is a simple method that counts down from 10.

Screen Shot 2017-10-13 at 7.37.29 AM.png

Notice this method calls itself. That’s recursion.

Here is another example. Say you have a datastructure has contains a parent, and then several children that reference other children like this.

Screen Shot 2017-10-13 at 7.40.22 AM.png

And say you want to convert this into a form where you could visualize this as nested subdirectories. Say a tree structure like this.

Screen Shot 2017-10-13 at 7.43.18 AM.png

Let’s start by making a function

Screen Shot 2017-10-13 at 7.45.06 AM.png

Then let’s call our makeTree function with categories and a starting parent of null. This will give us the first node with parent === null.

Screen Shot 2017-10-13 at 7.47.54 AM.png

Then what we are going to do is to take each element and assign it a node based on it’s id.

Screen Shot 2017-10-13 at 7.49.39 AM.png.

So now we have a node called animals.

Now here is where the magic happens. We are going to take that node and create the subtree by calling makeTree again passing in the same categories and parent for the next wave of subnodes, which happens to be this nodes id.

Screen Shot 2017-10-13 at 7.54.51 AM.png

So that’s an example of recursive. My other favorite example of recursion is in a binary tree. But we can look at that later.

Check out mpj’s excellent series for my videos like this.

 

JavaScript Currying #6

Leave a comment

Continuing my following of mpj’s series.

Currying is when a function, instead of taking all arguments at once, takes the first one and returns a new function, that takes the second one and returns a new function, which takes the third one and so on until all the arguments have been fulfilled.

Here it is in lodash.

Screen Shot 2017-10-13 at 6.45.33 AM.png

Another way of looking at it is like this. Here is a regular dragon function.

Screen Shot 2017-10-13 at 6.47.22 AM.png

And here is the curried version of the same function.

Screen Shot 2017-10-13 at 6.47.43 AM.png

In this curried version dragon is a function, that takes name as an argument, and returns a function that takes size as an argument, that returns another function that takes element as an argument, which in turn finally uses all three arguments.

And you call it, like this.

Screen Shot 2017-10-13 at 6.49.45 AM.png

This may look strange at first, but it’s not that bad. It’s just three method calls, all combined (or curried) together where a method keeps getting returned, and you simply chain the argument parameters. It does look strange. But that’s how it works. It’s just a chain of functions.

The idea with curries is that you can pass your function through your application, decorating it up and adding functions to it as you go.

For example we might break out various functions and call them in a more incremental manor like this.

Screen Shot 2017-10-13 at 6.53.54 AM.png

Now some tools/libraries, like lodash, help make your regular JS functions curriable. For example we have have left our dragon function like this. And then called it with lodash like this.

Screen Shot 2017-10-13 at 6.56.32 AM.png

Why is currying handy

Let’s say we start off with something like this, and we want to improve it with currying.

Screen Shot 2017-10-13 at 6.58.18 AM.png

Let’s import lodash, and curry has element.

Screen Shot 2017-10-13 at 7.00.46 AM.png

Then if you remove the wrapping function you can just do this

Screen Shot 2017-10-13 at 7.25.35 AM.png

What making hasElement curryable does it is means hasElement can return a new function, which takes a new argument which can be called from filter.

It’s still a bit weird. And I am still getting my head wrapped around it. But it looks like this could be handy for chaining function calls together, while passing arguments in just-in-time.

Javascript Closures

Leave a comment

 

In JS, functions are not just functions. They are also closures. What that means is that the function body has access to variables that are defined outside the function body.

Take this example.

Screen Shot 2017-10-13 at 5.20.06 AM.png

Here we are able to execute the variable var me, defined outside the function scope of the function, because JS functions are closures.

Other languages like Java, C#, and Objective-C don’t work like that. Normally you need to define the variable in the same scope of the function or method using it. Or by passing it in. But not in JS. Here functions (or closures) have access to variables define elsewhere.

So why are closures useful? Let’s look at this example.

Screen Shot 2017-10-13 at 5.26.54 AM.png

This asynchronous ajax method callback, will have access to requestId, even though it will be called asynchronously sometime in the future.

This is a good use of closures. What you want to start a task, and set some variables up for the future. This makes the code easier to read.

 

 

 

 

 

 

 

 

 

 

JavaScript reduce and mawr reduce

Leave a comment

map, filter, and reject transform lists into something else. map will take an array and transform that into an array of the same length but with each individual transformed.

filter and reject return new arrays based on whether each element of the array passes the passed in callback function.

and find behaves just like filter only it returns the first element.

There are lots of array transformations like this on the array object, but what should you do if you can’t find one that fits? That’s where reduce comes in.

map, filter, reject, and find are all list transformations. They are all pretty specific. But reduce is not. reduce is the multitool of list transformations.

The reduce() method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.

Screen Shot 2017-10-12 at 6.46.09 AM.png

Here is another example.

Screen Shot 2017-10-12 at 7.49.53 AM.png

And yet another example.

This one takes a file of tab delimited characters, and transforms them into JS literals.

It does this by:
* splitting on newlines
* mapping the lines into an array of arrays by splitting on tabs
* and then reducing

reduce takes two arguments. A function and a starting object. Because we are reducing to an object literal, here we start with an empty object literal.

Screen Shot 2017-10-13 at 4.44.43 AM.png

The function that wants to reduce takes two arguments.

Screen Shot 2017-10-13 at 4.50.00 AM.png

The first is the object was are constructing customer. For the first loop this will be our empty object literal {}. The second object is the thing we are iterating.

So reduce is going to receive this:

['mark johansson', 'waffle', 'iron', '80', '20']

If we ran this now we would get output undefind. And that is because our var output will be set to what reduce returns on it's final iteration. So lets return the customer object.

Screen Shot 2017-10-13 at 4.54.35 AM.png

If we ran this now we would still get an empty object, because we haven’t reduce anything yet.

Screen Shot 2017-10-13 at 4.55.57 AM.png

So let’s rename customer to be customers because we are accumulating customers and for every customer we are going to make customer with their name.

Screen Shot 2017-10-13 at 5.01.29 AM.png

Screen Shot 2017-10-13 at 5.01.49 AM.png

OK. There is a lot going on here. So let’s unpack this. What we are shooting for is this.

Screen Shot 2017-10-13 at 5.04.00 AM.png

And we have the beginning of that here. This line

Screen Shot 2017-10-13 at 5.04.55 AM.png

accumulates, or adds, a new array element every time with a key of line[0]</code which is the persons names, followed by it's value. In this case an empty []. That's what gives us this.

Screen Shot 2017-10-13 at 5.07.09 AM.png

Now all we have to do is build that inner array.

And we can do that, by pushing our remaining inner array values.

Screen Shot 2017-10-13 at 5.10.40 AM.png

There is one other gotcha. Because we want to keep reusing the existing customer line each time, and not override it, we modify this line here.

Screen Shot 2017-10-13 at 5.11.51 AM.png

 

And to better print out our JSON with 2 spaces we modify this line here.

Screen Shot 2017-10-13 at 5.12.36 AM.png

Second video.

JavaScript Map

Leave a comment

Map behave just like filter. It too is a function on the array object. Map will be passed each item in the elements array. But here is where map and filter are different.

Filter expects it’s callback function to return true or false indicating whether the element should be included in the newly returned array or not.

Map on the other hand will include all items in the array, but instead it expects the callback function to return a transformed object that it will put into the new array instead of the original animal. In this case – the name.

Screen Shot 2017-10-12 at 6.22.12 AM.png

Using map to return a subset of an object, is common. However, since map expects the callback to return any object, we can use it to return completely new objects.

Screen Shot 2017-10-12 at 6.27.41 AM.png

Screen Shot 2017-10-12 at 6.27.46 AM.png

The nice thing about methods like filter and map is it saves us from having to loop over each element in the array explicitly. It’s a lot less code.

And in ECMA6 it gets even better with arrow functions.

Screen Shot 2017-10-12 at 6.30.34 AM.png

Which can be further simplified to

Screen Shot 2017-10-12 at 6.31.18 AM.png

And it’s conventionally to not even include the object name. Just use x instead.

Screen Shot 2017-10-12 at 6.32.35 AM.png
Video.

JavaScript – Higher Order functions & filter

Leave a comment

Lately I have been watching a really good series on the fundamentals of JavaScript from mpj. Here are my notes.

Screen Shot 2017-10-12 at 5.55.36 AM.png

Because JS is a function based languages, functions play a much larger role in JS then they do in other languages. They are treated like variables and passed around.

In this case Array.prototype.filter() returns a new array based on whether the predicate returns true or false for each element of the array.

var words = ["spray", "limit", "elite", "exuberant", "destruction", "present"];

var longWords = words.filter(function(word){
  return word.length > 6;
});

E6 version

const words = ["spray", "limit", "elite", "exuberant", "destruction", "present"];

let longWords = words.filter(word => word.length > 6);

Video.

Older Entries

%d bloggers like this: