Refactoring legacy mixin-based class hierarchies

后端 未结 1 876
清酒与你
清酒与你 2020-12-04 01:12

I\'m currently working on a huge javascript project which has a huge class hierarchy and heavily uses mixins to extend functionality of base classes. Here is an example of h

1条回答
  •  既然无缘
    2020-12-04 01:45

    I did refactor the OP's example, and it does what was ask for. Let me know if I got something wrong.

    class BaseXYType {
    
      constructor(stateValue) { // injected state object.
    
        this.setX = function setX (x) {
          return (stateValue.x = x);
        };
        this.setY = function setY (y) {
          return (stateValue.y = y);
        };
    
        Object.defineProperty(this, "x", {
          get: function getX () {
            return stateValue.x;
          },
          enumerable: true
        });
        Object.defineProperty(this, "y", {
          get: function getY () {
            return stateValue.y;
          },
          enumerable: true
        });
    
        Object.defineProperty(this, 'valueOf', {
          value: function valueOf () {
            return Object.assign({}, stateValue);
          }
        });
        Object.defineProperty(this, 'toString', {
          value: function toString () {
            return JSON.stringify(stateValue);
          }
        });
      }
    
      setPosition(x, y) { // prototypal method.
        this.setX(x);
        this.setY(y);
        return this.valueOf();
      }
    }
    
    
    class SameXYType extends BaseXYType {
    
      // - Traits in JavaScript should be applicable types/objects that are
      //   just containers of trait and object composition rules which
      //   exclusively will be executed at a trait's apply time.
    
      constructor(stateValue) { // injected state object.
        super(stateValue);
    
        withSameInternalXAndYState.call(this, stateValue);
      }
    }
    
    
    var withSameInternalXAndYState = Trait.create(function (use, applicator) {
    
      // local functions in order to enable shared code, thus achieving less memory consumption.
      //
      function afterReturningStateChangeXHandler(returnValue, argsArray, payloadList) {
        var
          stateValue = payloadList[0];
    
        stateValue.y = argsArray[0];  // same y from x.
      }
      function afterReturningStateChangeYHandler(returnValue, argsArray, payloadList) {
        var
          stateValue = payloadList[0];
    
        stateValue.x = argsArray[0];  // same x from y.
      }
      function setPositionInterceptor(proceedSetPosition, interceptor, argsArray, payloadList) {
        var
          x = argsArray[0],
          y = argsArray[1];
    
        if (x !== y) {
          throw (new TypeError([x, "!==", y].join(" ")));
        }
        return proceedSetPosition.call(this, x, y);
      }
    
      applicator(function sameXAndYBehavior (stateValue) {
    
        // no additional trait specific behavior within the applicator
    
      }).requires([
    
          "setX",
          "setY",
          "setPosition"
    
      ]).afterReturning(
    
        "setX", afterReturningStateChangeXHandler
    
      ).afterReturning(
    
        "setY", afterReturningStateChangeYHandler
    
      ).around(
    
        "setPosition", setPositionInterceptor
      );
    });
    
    
    var
      base_1 = new BaseXYType({ x: 7, y: 11 }),
      base_2 = new BaseXYType({ x: 99, y: 1 }),
    
      same_1 = new SameXYType({ x: 13, y: 5 }),
      same_2 = new SameXYType({ x: 99, y: 1 });
    
    
    console.log('("" + base_1) : ', ("" + base_1));
    console.log('("" + base_2) : ', ("" + base_2));
    console.log('("" + same_1) : ', ("" + same_1));
    console.log('("" + same_2) : ', ("" + same_2));
    
    console.log('base_1.valueOf() : ', base_1.valueOf());
    console.log('base_2.valueOf() : ', base_2.valueOf());
    console.log('same_1.valueOf() : ', same_1.valueOf());
    console.log('same_2.valueOf() : ', same_2.valueOf());
    
    
    console.log('base_1.x : ', base_1.x);
    console.log('(base_1.x = "foo") : ', (base_1.x = "foo"));
    console.log('base_1.x : ', base_1.x);
    
    console.log('base_1.y : ', base_1.y);
    console.log('(base_1.y = "bar") : ', (base_1.y = "bar"));
    console.log('base_1.y : ', base_1.y);
    
    console.log('same_2.x : ', same_2.x);
    console.log('(same_2.x = "biz") : ', (same_2.x = "biz"));
    console.log('same_2.x : ', same_2.x);
    
    console.log('same_2.y : ', same_2.y);
    console.log('(same_2.y = "baz") : ', (same_2.y = "baz"));
    console.log('same_2.y : ', same_2.y);
    
    
    console.log('base_1.setY("foo") : ', base_1.setY("foo"));
    console.log('base_1.y : ', base_1.y);
    
    console.log('base_2.setX("bar") : ', base_2.setX("bar"));
    console.log('base_2.x : ', base_2.x);
    
    
    console.log('base_1.setPosition("brown", "fox") : ', base_1.setPosition("brown", "fox"));
    console.log('("" + base_1) : ', ("" + base_1));
    
    console.log('base_2.setPosition("lazy", "dog") : ', base_2.setPosition("lazy", "dog"));
    console.log('("" + base_2) : ', ("" + base_2));
    
    
    console.log('same_1.setY(543) : ', same_1.setY(543));
    console.log('same_1.x : ', same_1.x);
    console.log('same_1.y : ', same_1.y);
    console.log('same_1.valueOf() : ', same_1.valueOf());
    
    console.log('same_2.setY(79) : ', same_2.setY(79));
    console.log('same_2.x : ', same_2.x);
    console.log('same_2.y : ', same_2.y);
    console.log('same_2.valueOf() : ', same_2.valueOf());
    
    
    console.log('same_1.setPosition(77, 77) : ', same_1.setPosition(77, 77));
    console.log('("" + same_1) : ', ("" + same_1));
    
    console.log('same_2.setPosition(42, 42") : ', same_2.setPosition(42, 42));
    console.log('("" + same_2) : ', ("" + same_2));
    
    
    console.log('same_1.setPosition("apple", "pear") : ', same_1.setPosition("apple", "pear"));
    console.log('("" + same_1) : ', ("" + same_1));
    
    console.log('same_1.setPosition("apple", "pear") : ', same_1.setPosition("prune", "prune"));
    console.log('("" + same_1) : ', ("" + same_1));
    .as-console-wrapper { max-height: 100%!important; top: 0; }

    0 讨论(0)
提交回复
热议问题