Тестовое задание Cappers Applications Inc.
Нельзя редактировать существующие файлы, кроме stream-factory.ts, можно добавлять новые.
yarn installзапуск тестов
yarn test
- вернуть из класса StreamFactory пять разных реализаций IStream:
createFirstStream():
- запись и чтение из файла
createSecondStream():
- приводит каждый второй символ к верхнему регистру и записывает в файл
- читает из файла, затем меняет регистр каждому символу
createThirdStream():
- сортирует символы в строке и записывает в файл
- читает из файла и перемешивает символы
createFourthStream():
- приводит каждый второй символ к верхнему регистру, сортирует и записывает в файл
- читает из файла перемешивает и меняет регистр каждому символу
createFifthStream():
- сортирует, приводит каждый второй символ к верхнему регистру и записывает в файл
- читает из файла меняет регистр каждому символу и перемешивает
- найти недостатки в тестах
Экземпляр класса StreamFactory содержит фабричные методы, возвращающие экземпляры класса IStream<string> - абстракции файла с методами read и write:
+--------------------------+
| IStream<string> |
+==========================+
| read(): string |
| * read string from file |
| * map string |
| * return string |
+--------------------------+
| write(str: string): void |
| * get input string |
| * map string |
| * write string to file |
+--------------------------+
Для каждого метода на схеме описан алгоритм работы, из которой следует, что оба метода имеют стадию отображения строки: строка передается функции отображения mapper (функция принимающая оригинальную строку и возвращающая отображенную строку). Для метода read отображение строки происходит после считывания строки из файла (строка проходит последовательность отображений postReadMappers), для write - перед записью в файл (строка проходит последовательность отображений preWriteMappers). Разница между объектами, созданными разными фабриками, в наборе отображений, примененных к оригинальной строке, остальное поведение экземпляров идентичное.
Пример реализации методов StreamFactory в ООП:
Необходимо построить иерархию классов, базовый класс для абстракции файлов содержит:
- конструктор, принимающий путь к файлу;
- приватные методы операций чтения и записи (к примеру
private _read(): Promise<string>иprivate _write(str: string): Promise<void>); - публичные методы
read(возращенная_readстрока отображается черезthis.postReadMappersи возвращается методом) иwrite(переданная в метод строка отображается черезthis.preWriteMappersи передается в_write);
Классы, наследуемые от базового класса, содержат только приватные переменные this.postReadMappers и this.preWriteMappers с последовательностями отображений, применяемых к строке в методах базового класса read и write соответственно.
Парадигма ФП предоставляет большую гибкость по сравнению с ООП: нет иерархии классов, а значит меньшая связанность, добавляет абстракции, скрывающие низкоуровневые, естественная для ФП композиция функций отображений, фабрики объектов с разным поведением возвращаются функцией высшего прядка - фабрики фабрик, код получается более композируемым, открытым для расширения, удобным для тестирования.
Верхнеуровневая абстракция, является функцией высшего порядка, возвращает фабрику для разных реализаций IStream<string>. Принимает необходимые для того или иного вида абстракций файла списки функций отображений (preWriteMappers и postReadMappers).
Внутри createStreamFactory использует функции createReadWriteFile и composeMappers.
Принимает путь к файлу и возвращает асинхронные функции для чтения из файла (возвращенный Promise резолвится в строку, являющуюся содержимым файла) и записи в файл (принимает строку, которая будет записана в файл).
Является функцией высшего порядка, принимает последовательность функций отображения строки и возвращает результирующую функцию отображения.
+---------+ +---------+
original string -> | mapper1 | -> mapped string 1 -> | mapper2 | -> result string
+---------+ +---------+
аналогично:
+------------------------------------+
original string -> | composeMappers([mapper1, mapper2]) | -> result string
+------------------------------------+
Замечание: для оптимизации производительности функции отображения принимают и возвращают абстракции строки - массив символов, иначе в каждой функции отображение появится потребность преобразования строки в массив символов и обратно (обусловлено методами экземпляров String и Array в Javascript). Вместо этого composeMappers делает преобразование строки в массив до передачи в первую функции отображения и массива символов в строку после получения результата от последней.
Содержит доступные функции отображения абстракции строки.
Используя парадигму ФП, задача по созданию фабрики абстракции файла сводится к добавлению новой функции (или функций) отображения (mapper) и передаче в функцию createStreamFactory объекта, содержащего новые последовательности отображений полученной из файла и записываемой в файл абстракции строки. В случае ООП потребовалось бы так же добавить новую функцию (или функции) отображения, добавить новый класс со списком функций отображений для чтения и записи, импортировать и вызвать конструктор нового класса в классе StreamFactory.