couchdb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Alexander Shorin <>
Subject Re: [jira] [Commented] (COUCHDB-1397) Function expressions, evals in SpiderMonkey
Date Mon, 06 Feb 2012 02:39:32 GMT
Hi, Jason!

I'd like to share your disagreement about global functions (emit, log,
send etc.) if only I haven't rewritten query server line by line.
Actually, they are start to be global at function source code
compilation[1][2], so nobody stops you to change their context. But
you may notice, that view functions shares some invalid functions for
their context. e.g.
  emit(, 1);
    // ooops...(:
So you just wanted to have some control on function compilation
context? I suppose Couch[3] object could help you to define custom
context, overload default emit, log and other functions. May be using
Javascript query server internals a little unhandy, but some wrappers
could make it sweet(:

Hiding current "global" function to some object or module means
breaking all design function. Idea with requiring them (I mean your
`var couch=require("couch");`) looks nice from code design style, but
as lazy developer this looks like overhead that I should write because
without it my functions couldn't work at all! Not so relaxed as it
currently does.

About testing couchapps.
IMHO, there is no problem(: Function context could be easily
overloaded, but I dont think that unittests are good idea for them.

For testing Python couchapps I'd prefer black box testing[4] instead
of unit one because of some simple reasons.
Main profit of black box testing in this case that it works as is, I
dont have to care about mocking global function, emulating CommonJS,
mime type guessing routines etc. they are just have done well and
works well. If I need test against some CouchDB version, I just
specify target version and I'm aware about some specific behavior of
them - unittests couldn't get me such information.

For example, I could easily mock require function and make CommonJS
modules works for view functions, but these functions wouldn't
actually work in CouchDB before 1.1 version - this feature just was
not implement(:

Also, it's a simple task to test views, but much more pain you will
get by testing show and list functions[5], especially for second one
because they working in bi-direction way: reading input stream while
output is not finished, collecting chunks stack and flushing them back
for each getRow round...hellish function for well unit testing(:

So, resuming wall of text above:
0. Design function context could be customized;
1. Wrapping current pseudo global functions to CommonJS module or some
context object breaking a lot of code and makes it useless without
additional work;
2. Query server internals could help you in testing your couchapps;
3. Couchapps unittests are too synthetic and couldn't revive all
possible problems. Should you do same work twice?

// compilation
// namespace definition
// Couch object
// very simple and synthetic, but I'm awaiting for Dirkjan review of
current state before adding more features to simplify testing(:


On Mon, Feb 6, 2012 at 5:04 AM, Jason Smith <> wrote:
> Hi, Marcello and Alexander. Perhaps we can move this to the mailing
> list and off the JIRA ticket?
> On Sun, Feb 5, 2012 at 11:21 PM, Marcello Nuccio (Commented) (JIRA)
> <> wrote:
>>    [
>> Marcello Nuccio commented on COUCHDB-1397:
>> ------------------------------------------
>> @Alexander,
>> this isn't as off-topic as it seems at first, because software design is heavily
influenced by ease of testability.
> Firstly, I'm unsure if you noticed but I made a typo which gave my
> statement the opposite meaning.
> I agree that emit(), log(), etc. should NOT be global.
> However, I disagree that they should be passed to map(), simply
> because it burdens the programmer. Plus, if we add new functions in
> the future, it would change the call signature of map functions. On
> the other hand, we get the same benefit by passing the functions but
> using a closure to put them in scope of map(), reduce(), etc.
> The map function might be built like so (the example is imperfect but
> I'm aiming for clarity for now):
> Given: = "module.exports = function(doc) {
> emit(, 1) }"
> var make_map = Function("require, module, exports, emit, log",
> var map = make_map(require, module, exports, emit, log)
> map({name:"Bob"}) // Runs emit("Bob", 1)
> ## Unit testing
> It's imperfect for unit testing; however I think a hypothetical NPM
> package would be fine. It could convert the ddoc functions to
> JavaScript functions in a similar fashion. (Below is the first API
> that popped into my head, no doubt we could make better.)
> var assert = require('assert')
>  , couch = require('mock-couchdb')
> var ddoc = couch.load_ddoc({views: {people: {map: "function(doc) {
> emit(, 1) }"}}})
> var emitted
> ddoc.on('emit', function(key, val) { emitted = key })
> assert.equal(emitted, "Bob")
> --
> Iris Couch

View raw message