Видели подобный код?
void transform(String fileIn, String fileOut, String separatorIn, String separatorOut);
Только кажется простым, на самом деле сложно запоминать порядок параметров. Еще хуже, если есть другие дополнительные параметры (например, кодировки или для отправки на мейл):
void transform(String fileIn, String fileOut, String separatorIn, String separatorOut, String encoding, String mailTo, String mailSubject, String mailTemplate);
Чтобы внести изменения, нужно добавить еще один (перегруженный) метод transform
? Или добавить еще больше параметров в метод и обновлять каждый вызов transform
? Ни то, ни другое не ОК.
Одно из решений — инкапсулировать группы параметров в объекты значений. Класс CsvFile
здесь является таким «объектом значения» — просто контейнером данных.
class CsvFile { CsvFile(String filename, String separator, String encoding) { ... } String filename() { return filename; } String separator() { return separator; } String encoding() { return encoding; } } // ... and do the same for the EmailMessage class void transform(CsvFile src, CsvFile target, EmailMessage resultMsg) { ... }
Способы определения объекта значения (value object) зависят от языка. Например, в Java можно использовать класс record, который доступен начиная с Java 16+ (в старых версиях Java для генерации кода такого объекта можно применять AutoValue); в Kotlin — класс data; в C++ struct-опцию.
Применение объекта значения таким образом все равно может создавать длинные списки параметров при его инстанцировании. Решение этой проблемы зависит от языка. Например в Python для сокращения списка параметров можно использовать аргументы ключевых слов и дефолтные значения параметров; в Java одним из вариантов решения является паттерн Builder, который позволяет вызывать отдельную функцию для установки каждого поля и позволяет пропустить установку полей с дефолтными значениями.
CsvFile src = CsvFile.builder().setFilename("a.txt").setSeparator(":").build(); CsvFile target = CsvFile.builder().setFilename("b.txt").setEncoding(UTF_8).build(); EmailMessage msg = EmailMessage.builder().setMailTo(rcpt).setMailTemplate("template").build(); transform(src, target, msg);
Всегда старайтесь группировать «близкие» данные, и «разбивать» длинные сложные списки параметров. Такой код будет легче читать и поддерживать, и в нем будет меньше ошибок.