0

Terrible title, but this is the situation I find myself in often and have not found a good design to make it nice. Lets say I'm working with Javascript and I have an object I am working on that needs to persist to a DB when changes are made.

obj = {
  users : [
    {425: {name:'test'}},
    {427: {name:'test1'}},
    {450: {name:'test2'}},
  ],
  deleteUser : function(id){
     delete this.users[id];
     //maybe some other code (ui manipulation)
     this.persist();
  },
  deleteAllUsers : function(){
  var me = this;
    var uids = Object.keys(this.users);
    uids.forEach(function(u, i){
      me.deleteUser(i);
    });
    this.persist();
  },
  persist: function(){
    //some ajax call that persists the users array
    console.log('persist');
    return;
  },
};

obj.deleteAllUsers();

So right now, when you call deleteAllUsers it will persist on each call to deleteUser. I want deleteUser to skip the persist step since it will be called later in the calling function.

The two solutions I have thought of:

  1. Duplicate the code from deleteUser into deleteAllUsers and only persist at the end. (nope, that's terrible).

  2. Define deleteUser like deleteUser(id, persist), so we can specifiy in the persist argument if we should call persist or not. This is an ok solution, but I feel it's not ideal.

Is there any design pattern that deals with this? Or has anyone come up with a very clean way to deal with this situation?

3 Answers 3

1

For many cases, I just use the flag like your second example :

  deleteUser : function(id, isPersist){
     delete this.users[id];
     //maybe some other code (ui manipulation)

     if (isPersist)
         this.persist();
  }

  deleteAllUsers : function(){
  var me = this;
    var uids = Object.keys(this.users);
    uids.forEach(function(u, i){
      me.deleteUser(i, false);
    });

    this.persist();
  }

  persist: function(){
    //some ajax call that persists the users array
    console.log('persist');
    return;
  },

Occasionally though, I might have this structure :

  deleteSingleUser : function(id){
     me.deleteUser(id);
     this.persist();
  }

  deleteAllUsers : function(){
  var me = this;
    var uids = Object.keys(this.users);
    uids.forEach(function(u, i){
      me.deleteUser(i);
    });
    this.persist();
  }

  deleteUser : function(id){
     delete this.users[id];
     //maybe some other code (ui manipulation)
  }

  persist: function(){
    //some ajax call that persists the users array
    console.log('persist');
    return;
  }

(Naming convention could probably be better, to clarify which records persist to db and which only prepare for deletion without persisting. I'm too lazy to think of those now.)

Which I use typically depends on

  • If I have any custom code for deleting a Single user that should not run when deleting multiple users. In that case, the 2nd set of code is better.

  • If I ever want to delete a single user without persisting, such as allowing users to make multiple deletions without saving until they hit a "Save" button. In this case, I would use the first code segment with the isPersist flag.

  • How many places call deleteUser. If I am only calling it from one or two places, I much more likely to use a flag. But if I am doing it in many areas of the application, I am more likely to use the second case to avoid having to type the extra parameter for isPersist a lot.

2

By wrapping the whole thing in an IIFE, you can create private variables and functions. This way, the exposed API can wrap the private functions any which way, and persist would only be called when using the public delete:

var obj;
(function() {
    function realDelete(id) {
        delete obj.users[id];
        //maybe some other code (ui manipulation)
    }
    obj = {
      users : [
        {425: {name:'test'}},
        {427: {name:'test1'}},
        {450: {name:'test2'}},
      ],
      deleteUser : function(id){
         realDelete(id);
         this.persist();
      },
      deleteAllUsers : function(){
        var uids = Object.keys(this.users);
        uids.forEach(function(u, i){
            realDelete(i);
        });
        this.persist();
      },
      persist: function(){
        //some ajax call that persists the users array
        console.log('persist');
        return;
      },
    };
})();

obj.deleteAllUsers();
1

I think the interface to deleteUser() and deleteUsers() should be similar, so I'm against your second solution.

In this scenario, I'd keep the deleteUser() method, and internally delegate to a private persistence method. For consistency's sake, I would do the same for deleteUsers(). By doing that you're keeping the public interfaces consistent, and the internals consistent too (at the expense of a private method that is shared)

1
  • Any ideas for designing that internal interface? That's what I'm struggling with.
    – Dan
    Apr 26, 2016 at 16:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.