Register to get access to free programming courses with interactive exercises

Mutable configuration JS: Object oriented design

Many objects in OOP are not data abstractions, but rather are used as a way to save configurations to perform repetitive actions, such as generating HTML from Markdown, or determining a city by IP. Configuration is done by passing options to the object constructor, and the options themselves are stored internally and used for all subsequent calls.

// timeout sets a limit of one second for the duration of the query
const ipgeo = new IpGeo({ timeout: 1000 });
ipgeo.resolve('123.4.3.2');

But what if, for a particular query, you need to temporarily set options that are different from those passed to the constructor? There are three possible solutions to this situation.

Create a new object

The simplest solution is to create a new object where we want it. This solution, although simple, has a number of disadvantages. The main drawback is related to the fact that it's impossible to substitute the implementation (the same polymorphism that we'll talk about in the future), because the object isn't created at the system configuration stage, but rather at the place where the call takes place. This, in turn, leads to duplication of common options, and testing becomes difficult (if not impossible).

const ipgeo = new IpGeo({ timeout: 10 });
ipgeo.resolve('123.4.3.2');

Setters

The worst option involves the use of setters.

const ipgeo = new IpGeo({ timeout: 1000 });

// In one part of the program
ipgeo.resolve('123.4.3.2');

// In the other part of the program
ipgeo.setOption('timeout', 10);
ipgeo.resolve('123.4.3.2');

Variable state, the hardest thing in programming. The variable state is the root cause of almost all the problems we encounter and creates bugs that are dangerous and hard to catch. Guess what will go wrong after the last two lines? Our ipgeo object is shared by all parts of the system, which means that changing it in one place will affect all subsequent calls. In the case of Markdown, it gets more dangerous, because incorrect output creates security holes, specifically it makes it possible to perform XSS attacks:

const md = new Markdown({ sanitize: true });

// In one part of the program
md.render(markdown);

// Disable sanitize in the other part of the program
md.setOption('sanitize', false);
md.render(markdown2);

sanitize is the flag responsible for enabling safe rendering. If you turn it off, the <script> tags inserted in Markdown will be displayed as is. This is sometimes necessary and acceptable for your own text (for example,for lessons' texts of Hexlet), but unacceptable for text entered by users. Changing the md object creates a security hole. You can avoid it by remembering to put the option back:

const md = new Markdown({ sanitize: true });

// In one part of the program
md.render(markdown);

// Disable sanitize in the other part of the program
md.setOption('sanitize', false);
md.render(markdown2);
md.setOption('sanitize', true);

Programmers are bound to forget to do this, human error is always at play. This kind of code, in which something first changes one way and is then restored to a previous version, almost always indicates an architecture problem and can be rewritten in a safer form.

New options at query time

The appropriate approach solves all the problems mentioned above. It is based on passing an additional parameter to the method. This parameter contains temporary options that apply only to this query.

const md = new Markdown({ sanitize: true });

// In one part of the program
md.render(markdown);

// Turn off sanitize for the duration of the query in the other part of the program
md.render(markdown2, { sanitize: false });
md.render(markdown3); // sanitize is still true

Now everything is OK. Sanitize is enabled globally, but in one particular query, it was overridden by md.render(markdown, { sanitize: false }) This has no effect on subsequent calls of the render() method.


Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

About Hexlet learning process

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.bookmate">Bookmate</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.healthsamurai">Healthsamurai</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.dualboot">Dualboot</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.abbyy">Abbyy</span>
Suggested learning programs
profession
Development of front-end components for web applications
10 months
from scratch
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.