Шаблонный код

Шаблонный код, boilerplate-код (англ. boilerplate code) — нетворческий программный код, который программисту приходится писать вследствие требований языка программирования, операционной системы, библиотеки подпрограмм, манеры программирования и прочего. Шаблонными, в числе прочего, будут:

  • подключение модулей;
  • настройка компилятора и/или системы сборки;
  • организация точки входа в программу или подпрограмму;
  • код инициализации и выхода.

Например, в простейшем «Hello, world» на Си все строки, кроме собственно printf(...), будут шаблонными.

#include <stdio.h>                    //< шаблонный — подключение модуля
int main()                            //< шаблонный — точка входа
{                                     //< шаблонный — точка входа
  printf("Hello, world!\n");          //< творческий!!
  return 0;                           //< шаблонный — выход
}                                     //< шаблонный — точка входа

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

Этимология понятия «boilerplate»

Слово «boilerplate» по-английски означает «котельное железо». Применительно к шаблонному тексту встречается уже в 1950-х. Этимология неясна и определённо происходит из лексикона полиграфистов, основные версии.

  1. Местные американские газетки подписывались на новости у крупных печатных синдикатов, и те присылали готовые заметки в виде отлитых печатных форм. Эти формы и называли «котельным железом»[1][2].
  2. Печатные формы, которые нужны были многократно в нескольких выпусках газеты — для газетных шапок, объявлений от постоянных клиентов и т. д. — делали из железа, в то время как основная часть газеты набиралась из свинцового сплава[3].
  3. Дымогарный котёл требовал сверления множества отверстий, в которые вставляли дымогарные трубы. Для сверления использовали пластины-шаблоны, и написание стандартных объявлений сравнили с шаблонным сверлением отверстий[4][5].

Методы уменьшения количества шаблонного кода

Системы и библиотеки, решающие вопрос

Стандартный код на Java:

public class Book {
    private String m_ISBN;
    private String m_Title;
    private String m_SubTitle;
    private String m_Autor;

    public String getISBN() { return m_ISBN; }
    public void setISBN(String pISBN) { m_ISBN = pISBN; }

    public String getTitle() { return m_Title; }
    public void setTitle(String pTitle) { m_Title = pTitle; }

    public String getSubTitle() { return m_SubTitle; }
    public void setSubTitle(String pSubTitle) { m_SubTitle = pSubTitle; }

    public String getAutor() { return m_Autor; }
    public void setAutor(String pAutor) { m_Autor = pAutor; }
}

Аналогичный код на C#

public class Book
{
    public string ISBN { get; set; }
    public string Title { get; set; }
    public string SubTitle { get; set; }
    public string Autor { get; set; }
}

…и на Kotlin

data class Book(var ISBN: String, var Title: String, var SubTitle: String, var Autor: String)

Автогенераторы кода

Например, в системе Qt Widgets код минимальной формы с кнопкой имеет такой вид:

//== main.cpp ==
#include "FmMain.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    FmMain w;
    w.show();
    return a.exec();
}
//== FmMain.h ==
#ifndef FMMAIN_H
#define FMMAIN_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class FmMain; }
QT_END_NAMESPACE

class FmMain : public QMainWindow
{
    Q_OBJECT

public:
    FmMain(QWidget *parent = nullptr);
    ~FmMain();

private slots:
    void on_btDemo_clicked();

private:
    Ui::FmMain *ui;
};
#endif // FMMAIN_H
//== FmMain.cpp ==
#include "FmMain.h"
#include "ui_FmMain.h"

FmMain::FmMain(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::FmMain)
{
    ui->setupUi(this);
}

FmMain::~FmMain()
{
    delete ui;
}


void FmMain::on_btDemo_clicked()
{
    ui->btDemo->setText("Demo!!");    //< Только эту строку мы пишем вручную!
}

При этом только одну строку программист пишет вручную.

Препроцессоры

В том же Qt есть две программы, создающие часть Си++-кода формы — метаобъектный компилятор (moc) и компилятор интерфейса (uic).

Создание копии объекта с учётом умных указателей Си++11 выглядит так.

#include <iostream>
#include <memory>

class Abstract {
public:
    auto clone() const { return std::unique_ptr<Abstract>{ vclone() }; }
protected:
    virtual Abstract* vclone() const = 0;
};

class Abstract2 : public Abstract {
public:
    auto clone() const { return std::unique_ptr<Abstract2>{ vclone() }; }
protected:
    virtual Abstract2* vclone() const = 0;
};

class Concrete : public Abstract2 {
public:
    auto clone() const { return std::unique_ptr<Concrete>{ vclone() }; }
protected:
    Concrete* vclone() const override { return new Concrete(*this); }
};

int main()
{
    Concrete impl;

    Abstract* a = &impl;
    std::unique_ptr<Abstract> b = a->clone();
    std::unique_ptr<Concrete> c = impl.clone();

    return 0;
}

Здесь шаблонный код — реализации функций vclone и clone.

С препроцессором Си этот код будет выглядеть так, и чем больше классов в иерархии, тем больше выигрыш:

#define IMPL_CLONE_1(Class, Body)  \
    public:     auto clone() const { return std::unique_ptr<Class>{ vclone() }; } \
    protected:  virtual Class* vclone() const Body

#define IMPL_CLONE_ABSTRACT(Class) IMPL_CLONE_1(Class, override = 0;)
#define IMPL_CLONE_CONCRETE(Class) IMPL_CLONE_1(Class, override { return new Class(*this); })

class Abstract {
    IMPL_CLONE_1(Abstract, =0;)
};

class Abstract2 : public Abstract {
    IMPL_CLONE_ABSTRACT(Abstract2)
};

class Concrete : public Abstract2 {
    IMPL_CLONE_CONCRETE(Concrete)
};

Примечания

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.