Как писать Толковый ООП код в JS?

Всем доброго времени. Понимаю что вопрос глубокий но хотелось бы понять как писать годный код в ооп. Прогаю относительно недавно и при освоении ооп который должен был упростить код(как часто говорят на харбре))) вытоге уже сума меня сводить начал. Хотелось бы понимание в верном направлении я рою или нагромаздил черти че. Вот пример кода реализуещего на основе localStorage имитацию файловой системы для редактора. к нему еще несколько подобных фалов прилагается
const ul = "ul";
const li = "li";
const explorerlist = "explorer-list";
const sublist = 'explorer-sublist-item';
const projects = "projects";
const $toolbar = $("<div>", {
    class: "explorer-toolbar"
});
$toolbar.append($("<button>", {
    class: "explorer-toolbar-btn material-icons",
    title: "Create file",
    "data-action": "file-new",
    html: 'insert_drive_file'
}));
$toolbar.append($("<button>", {
    class: "explorer-toolbar-btn material-icons",
    title: "Create folder",
    "data-action": "folder-new",
    html: 'create_new_folder'
}));
$toolbar.append($("<button>", {
    class: "explorer-toolbar-btn material-icons",
    title: "Collapse all folders",
    "data-action": "collapse-all",
    html: 'indeterminate_check_box'
}));
$title = $("<div>", {
    "class": "explorer-input-wrapper"
}).append($("<input>", {
    "class": "explorer-input-field isBlured",
    "type": 'text',
    "data-action": "project-name",
    "placeholder": "Project Name"
}));
class EXPLORER {
    constructor() {
        this.treeID = explorerlist;
        this.p = {};
        this.opened = {};
        this.init()
    }
    init() {
        let opened = Local.get("opened");
        this.opened["project"] = opened["project"] || 0;
        this.opened["files"] = opened.files || [];
        Local.set("opened", this.opened);
    }
    get projects() {
        var p = Local.get(projects);
        for (var key in p) {
            let n = p[key]["name"];
            this.p[n] = p[key]
        }
        return Local.get(projects);
    }
    get Project() {
        var _this = this;
        return new class {
            open(name) {
                $title.attr("data-id", name).val(name);
                for (let i = 0; i < _this.projects.length; i++) {
                    if (name == _this.projects[i].name) {
                        const dir = _this.projects[i].dir;
                        Local.setKey("opened", "project", i);
                        Tree.showTree(ul, li, sublist, Tree.generate(dir), _this.$filetree);
                    }
                }
            }
            get projects() {
                var p = Local.get(projects);
                for (var key in p) {
                    let n = p[key]["name"];
                    _this.p[n] = p[key]
                }
                return _this.p
            }
        };
    }
    get File() {
        var _this = this;
        return new class {
            open(name) {
                let filesArr = Local.getKey("opened", "files");
                _this.file_path = {};
                var dir = Local.get("projects")[_this.opened.project].dir;
                dir.reduce((q, files) => {
                    const _file = files.substring(files.indexOf("/") + 1);
                    _this.file_path[_file] = files
                }, _this.file_path);
                if (_this.opened["project"] !== "undefined") {
                    var code = Local.get("projects")[_this.opened.project].files[name];
                    Workspace.Editors(_this.file_path[name]).create(code[1], _this.file_path[name]);
                    Workspace.Editors(_this.file_path[name]).instance.setValue(code[0]);
                    filesArr.push(_this.file_path[name]);
                    Local.setKey("opened", "files", filesArr);
                }
            }
            close(name) {
                let filesArr = Local.getKey("opened", "files");
                for (var i = 0; i < filesArr.length; i++)
                    if (filesArr[i] === name) filesArr.splice(i, 1)
                Local.setKey("opened", "files", filesArr);
            }
        }
    }
    render() {
        this.$explorer = $("#explorer");
        this.$filetree = $("<ul>", {
            class: explorerlist,
            id: explorerlist
        });
        this.$explorer.append($toolbar, $title, this.$filetree);
        event(this.$filetree, this);
        for (let i = 0; i < this.projects.length; i++) {
            if (i == this.opened["project"]) {
                this.Project.open(this.projects[i]["name"]);
            }
        }
    }
}
var event = (elem, explorer) => {
    $(document).on('click touchend', elem, e => {
        if ($(e.target).parent('li').hasClass(sublist)) {
            $(e.target).parent('li').toggleClass('active');
        }
        if ($(e.target).parent('li').hasClass('explorer-file')) {
            let elem = e.target,
                str = '';
            if (!elem && elem === this.$filetree) return
            elem = $(e.target).parent().parent('li');
            let dir = elem ? elem.children().text() : '';
            str = `${str && dir ? `${dir}/` : dir}${str}`;
        }
    });
    $(document).on('dblclick touchend', elem, e => {
        if ($(e.target).parent().hasClass('explorer-file-item')) {
            var name = $(e.target).text();
            explorer.File.open(name);
        }
    });
    $(document).on("change", $title, (e) => {
        var projName = $(e.target).attr("data-id")
        var projects = EXPLORER.projects;
        for (var key in projects) {
            if (projects[key]["name"] == projName) {
                projects[key]["name"] = $(e.target).val();
                Local.set(projects, projects)
            }
        }
    });
}

function initMode(fileExtension) {
    switch (fileExtension) {
        case "html" || "xml":
            return "htmlmixed";
        case "js":
            return "javascript";
        case "css":
            return "css";
    }
}
function getFormat(text) {
    return text.split(".").pop()
}

Если есть какие статейки на примете подкиньте плз. Те что нашел на харбре и мозиле весьма примитивны и не дают понго представления приминения сих принципов на практике
  • Вопрос задан
  • 6823 просмотра
Пригласить эксперта
Ответы на вопрос 5
@MadridianFox
Web-программист, многостаночник
Понимание ООП приходит с опытом. Сначала надо написать много кода, самому заметить его недостатки и тогда перечитывая те же самые статейки вы начнёте по новому понимать, что вот конкретно эту штуку можно было бы использовать в том моём коде, и было бы лучше.

Я разделяю ООП на аутентичное и классическое. Аутентичное, это ООП как его представлял автор - объекты обмениваются сообщениями.
Классическое - это то как оно реализовано в Java.
И там и там есть инкапсуляция и полиморфизм. Наследование это приятная фишка классического ООП. Так же как и все пляски с типами. Вообще строгая типизация не является частью ООП. По крайней мере не является частью аутентичного ООП.

Поэтому переход на typescript позволит только более точно воспроизводить классическое ООП. Ну и проверку типов добавит. Это само по себе полезно, но для ООП никакого значения не имеет.

В общем,. Надо всегда помнить о двух вещах - инкапсуляция и полиморфизм. Необходимо выделять некоторую самостоятельную функциональность в отдельные объекты и писать код так, чтобы решение о том какой код выполнить делалось не кучей условий, а на основании того, какой объект сейчас лежит в переменной.

Заметьте, про js я почти ничего не сказал. Потому что дело не в нём. Дело только в понимании ООП. У языков программирования, конечно, есть различные возможности и ограничения что которые позволяют использовать ту или иную парадигму. Но ООП на js можно было делать и до es6, просто потому что в js можно инкапсулировать код в объект.

И ещё, когда мы начинаем делить код на объекты, необходим механизм разделения кода на файлы и собирания его обратно. Т.е. нужна модульность. Лучше всего, конечно, использовать webpack, но вроде как в js есть и другие системы. Не сборки, а именно подключения модулей.
Ответ написан
yurakostin
@yurakostin
Front-end developer
На мой вкус там, где ООП - там паттерны, а где паттерны - там не обязательно должно быть ООП.
Вы должны понимать, зачем вы создаёте все ваши классы. Какую проблему они решают.

Вот достаточно популярный ресурс по паттернам.

Если вы хотите прям ООП-ООП, то у вас более половины вашего кода должно быть написано иначе(а ещё лучше на ООП языке типа Java). Не должно быть просто вызовов функций: вся работа через объекты. Никаких `$toolbar.append` и прочего.

Опять же, я могу быть глубоко не прав, но js ни ООП, ни ФП подход не реализует в полной мере. Поэтому только и остаётся, что писать в каком-то гибридном стиле. Возможно, что это огромная проблема языка, возможно наоборот.
Ответ написан
@letMeDie
Не знаю что там по статейкам, но лучше переходи на Typescript.
Ответ написан
1. Представление (работа с DOM) должно быть изолировано
2. return new class - не надо так
3. ... остальное проще рассматривать при решении предыдущих пунктов
Ответ написан
@777Polar_Fox777
JQuerry? Классы в JS? Кошмар. Лучше переходи на функции и React
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
IT IS Kernel Новосибирск
от 100 000 руб.
SKILLARY Москва
от 100 000 руб.
HTML Academy Санкт-Петербург
от 150 000 до 180 000 руб.
21 сент. 2019, в 00:13
5000 руб./за проект
20 сент. 2019, в 20:02
3000 руб./за проект
20 сент. 2019, в 19:04
80000 руб./за проект