Ich hatte die beiden Member-Funktionen von MyClass
:Kann dieser Code ohne Laufzeitauswirkung faktorisiert werden?
Result MyClass::func1(const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const ExtraParam1& extraParam1)
{
Result result;
// prolog code, common to all, using commonParam1, commonParam2, commonParam3
doSomething(1, commonParam1, commonParam2, extraParam1);
// epilog code, common to all, using commonParam1, commonParam2, commonParam3
return result;
}
Result MyClass::func2(const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const ExtraParam2& extraParam2, const ExtraParam3& extraParam3)
{
Result result;
// prolog code, common to all, using commonParam1, commonParam2, commonParam3
doSomething(1, commonParam1, commonParam2, extraParam2, extraParam3);
// epilog code, common to all, using commonParam1, commonParam2, commonParam3
return result;
}
Ich muss das faktorisieren Duplizierung von prolog/Epilog-Code zu vermeiden, die für beide funktionieren genau gleich sind (wird modifiziert MyClass Attribute, Prologs erstellt verwendeten Variablen durch Epilog ... Zeug wie das). Der einzige Unterschied ist, dass eine andere Version von MyClass::doSomething
aufgerufen wird (mit anderen Parametern). Als doSomething
mit einem anderen Satz von Parametern aufgerufen wird, habe ich diesen Ansatz für Faktorisierung Vorlage und die Einführung eine Helfer-Klasse:
class helper1
{
public:
helper1(const ExtraParam1& extraParam1) : extraParam1(extraParam1) {}
inline bool compute(MyClass& parent, const CommonParam& commonParam1, const CommonParam& commonParam2) const
{
return parent.doSomething(1, commonParam1, commonParam2, extraParam1);
}
private:
const ExtraParam1& extraParam1;
};
class helper2
{
public:
helper2(const ExtraParam2& extraParam2, const ExtraParam3& extraParam3) : extraParam2(extraParam2), extraParam3(extraParam3) {}
inline bool compute(MyClass& parent, const CommonParam& commonParam1, const CommonParam& commonParam2) const
{
return parent.doSomething(1, commonParam1, commonParam2, extraParam2, extraParam3);
}
private:
const ExtraParam2& extraParam2;
const ExtraParam3& extraParam3;
};
template<typename Helper>
inline Result funcT(MyClass& parent,
const CommonParam& commonParam1,
const CommonParam& commonParam2,
const CommonParam& commonParam3,
const Helper& helper)
{
// this function is a friend of MyClass, so prolog/epilog can use any private class attribute
Result result;
// prolog code, common to all, using commonParam1, commonParam2, commonParam3
helper.compute(parent, commonParam1, commonParam2);
// epilog code, common to all, using commonParam1, commonParam2, commonParam3
return result;
}
Result MyClass::func1(const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const ExtraParam1& extraParam1)
{
return funcT(*this, commonParam1, commonParam2, commonParam3, helper1(*this, extraParam1));
}
Result MyClass::func2(const CommonParam& commonParam1, const CommonParam& commonParam2, const CommonParam& commonParam3, const ExtraParam2& extraParam2, const ExtraParam3& extraParam3)
{
return funcT(*this, commonParam1, commonParam2, commonParam3, helper2(*this, extraParam2, extraParam3));
}
Diese Funktionen sind Milliarden mal von unserem Algorithmus genannt, so muss das Refactoring hat die niedrigste Laufzeitauswirkung.
compute
ist inline
und alles wird als Referenz übergeben und ich verwendete Vorlage statt virtuelle Tabelle, um Laufzeitauswirkungen zu minimieren. Ich denke jedoch, dass dies zur Laufzeit Auswirkungen hat (zumindest erzeugen wir helper1
, helper2
Objekte).
Hat mein Refactoring Auswirkungen auf die Laufzeit, die der Compiler nicht entfernen wird? Wenn ja, könnte jemand ein Refactoring mit geringerer Laufzeit vorschlagen?