0

Let's suppose that I have this piece of code:

function drawToCanvas() {
    const canvas = document.createElement('canvas');

    const context = canvas.getContext('2d');

    context.rect(10, 10, 100, 100);
    context.fill();

    const visibleCanvas = document.getElementById('mycanvas');
    const visibleContext = visibleCanvas.getContext('2d');

    visibleContext.drawImage(canvas, 0, 0);

    return visibleCanvas;
}

From the point of view of the LoD, the first part of this function is essentially equivalent to

document.createElement('canvas').getContext('2d').rect(10, 10, 100, 100);

Where the second part is not so different.

How should I use dependency injection to prevent this, and at the same time preserve the reference to the canvas and its context?

Shokry
  • 81
  • 1
  • 7

2 Answers2

0

The LoD is a guideline, a design pattern, not a strict rule.

But if you look at it a different way, you don't necessarily violate the LoD using this technique:

You use the canvas and you use its ctx directly. In this case, you create a relation between your class and the context returned by the canvas. At this point, your context is now a direct "neighbour", although, yes, it it a little bit cheated here.

You often have to use sub-objects of currently related objects (like array.item.toString()) to avoid the unnecessary creation of a collection for every single task you want to perform.

Same as database normalization: It is a helpful guideline to keep you on the right track, but sometimes you need to break it to keep your classes structured and your code working (in case of normalization it is sometimes needed for a better performance, to create redundant or compressed data, in a matter of materialized views).

Psi
  • 6,387
  • 3
  • 16
  • 26
0

(Reposting here, since I keep running out of comment space.)

Euh, I'm not sure if I understand correctly, but wouldn't just using a parameter for the canvas id satisfy LoD? Since the canvas is scoped to this function, and the only link is the parameter ('mycanvas') in this case, you are only operating on your own function arguments. And imho, if you see the context as a different object than the canvas, hence .createElement().getContext().rect() violates LoD, you're just in for alot of trouble. Imho, any built-in JS methods should not be subject to LoD, since rewrapping all the builtins in their own object, just to satisfy LoD, looks overly verbose.

Besides, JS is not strictly OOP and alot of code is modularized and namespaced. So often you can't avoid, and alot of people even prefer, doing things like basic JQuery chaining: $('someSelector').find('someChild').attr('someChange'); As long as a module itsself doesn't break seperation of concerns and single responsability (even if that responsibility is big, like create/render a full widget), I personally don't mind using 'shortcuts' like chaining methods from different objects together in the module itsself.

If you try to stick to pure functions and a clear public interface for all modules, you automatically avoid alot of the issues LoD helps prevent in OOP only enviroments.

As a last note, in stack exchange programmers or stack exchange software engineering, people will probably be able to help you better than in the JS section, since this is more broadly than JS only.

Shilly
  • 8,511
  • 1
  • 18
  • 24