Генерація коду є важливою складовою розробки програмного забезпечення, особливо у великих проектах з великою кількістю однотипних або стандартизованих функцій. Одним із інструментів, що полегшують цей процес, є бібліотека Sourcery, яка дозволяє генерувати код на основі шаблонів. Проте, іноді можуть виникати проблеми при створенні шаблонів для загальних методів, особливо коли потрібно взяти до уваги типи даних, що можуть бути загальними.
Однією з таких проблем є виникнення запиту про допомогу у виведенні типу <T: Codable>
із методу, який повертає загальний об’єкт. Давайте розглянемо цю проблему та можливі шляхи її вирішення.
Почнемо з розбору коду, який викликає проблеми. Маємо метод:
1 |
func get<T: Codable>(for key: String) -> T? |
Цей метод призначений для отримання об’єкта типу T за ключем key із деякого джерела даних. Однак, проблема виникає при спробі створення шаблону для генерації коду з цим методом.
Для розв’язання цієї проблеми потрібно аналізувати шаблон, який використовується для генерації коду. Ось фрагмент шаблону AutoStub.stencil
, який використовується для генерації:
1 2 3 4 5 6 7 8 |
{% raw %} {% macro methodReturnNameAndType method -%} {%- if method.isGeneric -%} {%- call methodReturnName method -%} : {{ method.returnTypeName }} // <- I'm stuck on this {%- else -%} {% call methodReturnName method %}: {% call methodReturnType method %} {%- endif -%} {%- endmacro -%} {% endraw %} |
Важливим моментом є те, що у шаблоні використовується підстановка типу повернення методу. Проте, у випадку, коли метод має загальний тип <T: Codable>
, це може призвести до проблем, оскільки тип повернення не може бути просто виведений із методу.
Щоб вирішити цю проблему, можна розглянути декілька варіантів. Один із них – це використання додаткового шаблону або умовного оператора для визначення типу повернення для загальних методів. Наприклад, можна додати умовний оператор, який перевіряє, чи є метод загальним, і, якщо так, встановлює тип повернення як <T>
.
Ось як можна модифікувати фрагмент шаблону, щоб врахувати тип повернення для загальних методів:
1 2 3 4 5 6 7 8 9 |
{% raw %} {% macro methodReturnNameAndType method -%} {%- if method.isGeneric -%} {%- call methodReturnName method -%} : <T> // Встановлюємо тип повернення як <T> {%- else -%} {% call methodReturnName method %}: {% call methodReturnType method %} {%- endif -%} {%- endmacro -%} {% endraw %} |
Зазначений вище код буде враховувати тип повернення як <T>
у випадку, коли метод є загальним, що дозволить коректно генерувати код.
Оскільки це лише один із можливих шляхів вирішення проблеми, варто також розглянути інші підходи та варіанти оптимізації шаблонів для забезпечення коректної роботи з загальними методами.