Topic: Contracts - separation of concerns
Author: morwenn29@gmail.com
Date: Fri, 7 Mar 2014 01:40:33 -0800 (PST)
Raw View
------=_Part_393_32434552.1394185233289
Content-Type: text/plain; charset=UTF-8
I was reading the latest paper about preconditions for the C++ programming
languages and it reminded me of some courses I had about aspect programming
and separation of concerns.
Of course, I don't propose to add aspects to C++ (there's already AspectC++
for that), but I find that separating the concerns is still a good idea.
A while ago, I tried to create some classes and functions to separate
preconditions and postconditions from the body of some functions.
Here is an example of what I managed to create:
struct Foo
{
static unsigned sum(unsigned a, unsigned b)
{
return a + b;
}
static double sqrt(double a)
{
return std::sqrt(a);
}
static double bar(int a)
{
return double(a);
}
};
template<>
struct make_contract<Foo>:
Foo
{
static unsigned sum(unsigned a, unsigned b)
{
// precondition: none
auto res = Foo::sum(a, b);
// postcondition:
assert(res >= a+b);
return res;
}
static double sqrt(double a)
{
// precondition:
assert(a >= 0.0);
auto res = Foo::sqrt(a);
// postcondition: none
return res;
}
// If a function from Foo is not checked here, the
// unchecked function will be used instead
// It is the case of bar in this example
};
int main()
{
// contract<Foo> checks the conditions in debug mode
// but is the same as Foo if NDEBUG is defined
using math = contract<Foo>;
double a = math::bar(5);
double b = math::sqrt(4.0);
double c = math::sqrt(-2.0); // Should crash here in debug mode
int d = math::sum(2, 3);
int e = math::sum(9, 10);
std::cout << a << std::endl;
std::cout << b << std::endl;
std::cout << c << std::endl;
std::cout << d << std::endl;
std::cout << e << std::endl;
}
The global idea is that contract will inherit directly from Foo is NDEBUG
is defined, and will inherit from make_contract<Foo> in debug mode.
Here are the declarations of contract and make_contract:
template<typename T>
struct make_contract;
template<typename T>
struct contract:
#ifndef NDEBUG
make_contract<T>
#else
T
#endif
{
#ifndef NDEBUG
using make_contract<T>::make_contract;
#else
using T::T;
#endif
};
That's only an idea, not a real proposal in any way. Here are the questions
I want to raise:
- Do we want to separate such concerns?
- [preconditions and postconditions do not need to know the internals of
a function]
- Is this particualr design flawed by nature?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_393_32434552.1394185233289
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I was reading the latest paper about preconditions for the=
C++ programming languages and it reminded me of some courses I had about a=
spect programming and separation of concerns.<br>Of course, I don't propose=
to add aspects to C++ (there's already AspectC++ for that), but I find tha=
t separating the concerns is still a good idea.<br>A while ago, I tried to =
create some classes and functions to separate preconditions and postconditi=
ons from the body of some functions.<br>Here is an example of what I manage=
d to create:<br><br><pre style=3D"margin-left: 40px;"><div class=3D"line" i=
d=3D"LC10"><span class=3D"k">struct</span> <span class=3D"n">Foo</span></di=
v><div class=3D"line" id=3D"LC11"><span class=3D"p">{</span></div><div clas=
s=3D"line" id=3D"LC12"> <span class=3D"k">static</sp=
an> unsigned <span class=3D"n">sum</span><span class=3D"p">(</span><span cl=
ass=3D"kt">unsigned</span> <span class=3D"n">a</span><span class=3D"p">,</s=
pan> <span class=3D"kt">unsigned</span> <span class=3D"n">b</span><span cla=
ss=3D"p">)</span></div><div class=3D"line" id=3D"LC14"> &n=
bsp;<span class=3D"p">{</span></div><div class=3D"line" id=3D"LC15"> &=
nbsp; <span class=3D"k">return</span> <s=
pan class=3D"n">a</span> <span class=3D"o">+</span> <span class=3D"n">b</sp=
an><span class=3D"p">;</span></div><div class=3D"line" id=3D"LC16"> &n=
bsp; <span class=3D"p">}</span></div><div class=3D"line" id=3D"L=
C17"><br></div><div class=3D"line" id=3D"LC18"> <spa=
n class=3D"k">static</span> double<span class=3D"k"></span> <span class=3D"=
n">sqrt</span><span class=3D"p">(</span><span class=3D"kt">double</span> <s=
pan class=3D"n">a</span><span class=3D"p">)</span></div><div class=3D"line"=
id=3D"LC20"> <span class=3D"p">{</span></div><div c=
lass=3D"line" id=3D"LC21"> <=
span class=3D"k">return</span> <span class=3D"n">std</span><span class=3D"o=
">::</span><span class=3D"n">sqrt</span><span class=3D"p">(</span><span cla=
ss=3D"n">a</span><span class=3D"p">);</span></div><div class=3D"line" id=3D=
"LC22"> <span class=3D"p">}</span></div><div class=
=3D"line" id=3D"LC23"><br></div><div class=3D"line" id=3D"LC24">  =
; <span class=3D"k">static</span> <span class=3D"k">double</span=
> <span class=3D"n">bar</span><span class=3D"p">(</span><span class=3D"kt">=
int</span> <span class=3D"n">a</span><span class=3D"p">)</span></div><div c=
lass=3D"line" id=3D"LC26"> <span class=3D"p">{</span=
></div><div class=3D"line" id=3D"LC27"> =
<span class=3D"k">return</span> <span class=3D"kt">double</span=
><span class=3D"p">(</span><span class=3D"n">a</span><span class=3D"p">);</=
span></div><div class=3D"line" id=3D"LC28"> <span cl=
ass=3D"p">}</span></div><div class=3D"line" id=3D"LC29"><span class=3D"p">}=
;<br><br></span></div><div class=3D"line" id=3D"LC44"><span class=3D"n"></s=
pan>template<span class=3D"p"><><br>struct make_contract<Foo>:<=
br> Foo<br>{</span></div><div class=3D"line" id=3D"LC45"> &nb=
sp; <span class=3D"k">static</span> unsigned <span class=3D"n">sum</span><s=
pan class=3D"p">(</span><span class=3D"kt">unsigned</span><span class=3D"kt=
"></span> <span class=3D"n">a</span><span class=3D"p">,</span> <span class=
=3D"kt">unsigned</span><span class=3D"kt"></span> <span class=3D"n">b</span=
><span class=3D"p">)</span></div><div class=3D"line" id=3D"LC47"> &nbs=
p; <span class=3D"p">{</span></div><div class=3D"line" id=3D"LC48">&n=
bsp; <span class=3D"c1">// precondition=
: none</span></div><div class=3D"line" id=3D"LC49"> =
<span class=3D"k">auto</span> <span class=3D"n">res</spa=
n> <span class=3D"o">=3D</span> <span class=3D"n">Foo</span><span class=3D"=
o">::</span><span class=3D"n">sum</span><span class=3D"p">(</span><span cla=
ss=3D"n">a</span><span class=3D"p">,</span> <span class=3D"n">b</span><span=
class=3D"p">);</span></div><div class=3D"line" id=3D"LC50"> &nb=
sp; <span class=3D"c1">// postcondition:</span></di=
v><div class=3D"line" id=3D"LC51">  =
; assert<span class=3D"n"></span><span class=3D"p">(</span><span class=3D"n=
">res</span> <span class=3D"o">>=3D</span> <span class=3D"n">a</span><sp=
an class=3D"o">+</span><span class=3D"n">b</span><span class=3D"p">);</span=
></div><div class=3D"line" id=3D"LC52"> =
<span class=3D"k">return</span> <span class=3D"n">res</span><span cl=
ass=3D"p">;</span></div><div class=3D"line" id=3D"LC53"> =
<span class=3D"p">}</span></div><div class=3D"line" id=3D"LC54"><br></div><=
div class=3D"line" id=3D"LC55"> <span class=3D"k">static<=
/span> double <span class=3D"n">sqrt</span><span class=3D"p">(</span><span =
class=3D"kt">double</span> <span class=3D"n">a</span><span class=3D"p">)</s=
pan></div><div class=3D"line" id=3D"LC57"> <span class=3D=
"p">{</span></div><div class=3D"line" id=3D"LC58"> &=
nbsp; <span class=3D"c1">// precondition:</span></div><div clas=
s=3D"line" id=3D"LC59"> assert<sp=
an class=3D"n"></span><span class=3D"p">(</span><span class=3D"n">a</span> =
<span class=3D"o">>=3D</span> <span class=3D"mf">0.0</span><span class=
=3D"p">);</span></div><div class=3D"line" id=3D"LC60"> &nb=
sp; <span class=3D"k">auto</span> <span class=3D"n">res</=
span> <span class=3D"o">=3D</span> <span class=3D"n">Foo</span><span class=
=3D"o">::</span><span class=3D"n">sqrt</span><span class=3D"p">(</span><spa=
n class=3D"n">a</span><span class=3D"p">);</span></div><div class=3D"line" =
id=3D"LC61"> <span class=3D"c1">/=
/ postcondition: none</span></div><div class=3D"line" id=3D"LC62"> &nb=
sp; <span class=3D"k">return</span> <span cla=
ss=3D"n">res</span><span class=3D"p">;</span></div><div class=3D"line" id=
=3D"LC63"> <span class=3D"p">}</span></div><div class=3D"=
line" id=3D"LC64"><br></div><div class=3D"line" id=3D"LC65"> &nb=
sp; <span class=3D"c1">// If a function from Foo is not checked here, the</=
span></div><div class=3D"line" id=3D"LC66"> <span class=
=3D"c1">// unchecked function will be used instead</span></div><div class=
=3D"line" id=3D"LC67"> <span class=3D"c1">// It is the ca=
se of bar in this example</span></div><div class=3D"line" id=3D"LC68"><span=
class=3D"p">};</span></div><div class=3D"line" id=3D"LC71"><br></div><div =
class=3D"line" id=3D"LC72"><span class=3D"kt">int</span> <span class=3D"n">=
main</span><span class=3D"p">()</span></div><div class=3D"line" id=3D"LC73"=
><span class=3D"p">{</span></div><div class=3D"line" id=3D"LC74"> &nbs=
p; <span class=3D"c1">// contract<Foo> checks the conditio=
ns in debug mode</span></div><div class=3D"line" id=3D"LC75"> &n=
bsp; <span class=3D"c1">// but is the same as Foo if NDEBUG is defined=
</span></div><div class=3D"line" id=3D"LC76"> <span =
class=3D"k">using</span> <span class=3D"n">math</span> <span class=3D"o">=
=3D</span> <span class=3D"n">contract</span><span class=3D"o"><</span><s=
pan class=3D"n">Foo</span><span class=3D"o">></span><span class=3D"p">;<=
/span></div><div class=3D"line" id=3D"LC77"></div><div class=3D"line" id=3D=
"LC78"><br></div><div class=3D"line" id=3D"LC79"> <s=
pan class=3D"kt">double</span> <span class=3D"n">a</span> <span class=3D"o"=
>=3D</span> <span class=3D"n">math</span><span class=3D"o">::</span><span c=
lass=3D"n">bar</span><span class=3D"p">(</span><span class=3D"mi">5</span><=
span class=3D"p">);</span></div><div class=3D"line" id=3D"LC80"><br></div><=
div class=3D"line" id=3D"LC81"> <span class=3D"kt">d=
ouble</span> <span class=3D"n">b</span> <span class=3D"o">=3D</span> <span =
class=3D"n">math</span><span class=3D"o">::</span><span class=3D"n">sqrt</s=
pan><span class=3D"p">(</span><span class=3D"mf">4.0</span><span class=3D"p=
">);</span></div><div class=3D"line" id=3D"LC82"> <s=
pan class=3D"kt">double</span> <span class=3D"n">c</span> <span class=3D"o"=
>=3D</span> <span class=3D"n">math</span><span class=3D"o">::</span><span c=
lass=3D"n">sqrt</span><span class=3D"p">(</span><span class=3D"o">-</span><=
span class=3D"mf">2.0</span><span class=3D"p">);</span> <span class=3D"c1">=
// Should crash here in debug mode</span></div><div class=3D"line" id=3D"LC=
83"><br></div><div class=3D"line" id=3D"LC84"> <span=
class=3D"kt">int</span> <span class=3D"n">d</span> <span class=3D"o">=3D</=
span> <span class=3D"n">math</span><span class=3D"o">::</span><span class=
=3D"n">sum</span><span class=3D"p">(</span><span class=3D"mi">2</span><span=
class=3D"p">,</span> <span class=3D"mi">3</span><span class=3D"p">);</span=
></div><div class=3D"line" id=3D"LC85"> <span class=
=3D"kt">int</span> <span class=3D"n">e</span> <span class=3D"o">=3D</span> =
<span class=3D"n">math</span><span class=3D"o">::</span><span class=3D"n">s=
um</span><span class=3D"p">(</span><span class=3D"mi">9</span><span class=
=3D"p">,</span> <span class=3D"mi">10</span><span class=3D"p">);</span></di=
v><div class=3D"line" id=3D"LC86"><br></div><div class=3D"line" id=3D"LC87"=
> <span class=3D"n">std</span><span class=3D"o">::</=
span><span class=3D"n">cout</span> <span class=3D"o"><<</span> <span =
class=3D"n">a</span> <span class=3D"o"><<</span> <span class=3D"n">st=
d</span><span class=3D"o">::</span><span class=3D"n">endl</span><span class=
=3D"p">;</span></div><div class=3D"line" id=3D"LC88"> &nbs=
p;<span class=3D"n">std</span><span class=3D"o">::</span><span class=3D"n">=
cout</span> <span class=3D"o"><<</span> <span class=3D"n">b</span> <s=
pan class=3D"o"><<</span> <span class=3D"n">std</span><span class=3D"=
o">::</span><span class=3D"n">endl</span><span class=3D"p">;</span></div><d=
iv class=3D"line" id=3D"LC89"> <span class=3D"n">std=
</span><span class=3D"o">::</span><span class=3D"n">cout</span> <span class=
=3D"o"><<</span> <span class=3D"n">c</span> <span class=3D"o"><<=
;</span> <span class=3D"n">std</span><span class=3D"o">::</span><span class=
=3D"n">endl</span><span class=3D"p">;</span></div><div class=3D"line" id=3D=
"LC90"> <span class=3D"n">std</span><span class=3D"o=
">::</span><span class=3D"n">cout</span> <span class=3D"o"><<</span> =
<span class=3D"n">d</span> <span class=3D"o"><<</span> <span class=3D=
"n">std</span><span class=3D"o">::</span><span class=3D"n">endl</span><span=
class=3D"p">;</span></div><div class=3D"line" id=3D"LC91"> &nbs=
p; <span class=3D"n">std</span><span class=3D"o">::</span><span class=
=3D"n">cout</span> <span class=3D"o"><<</span> <span class=3D"n">e</s=
pan> <span class=3D"o"><<</span> <span class=3D"n">std</span><span cl=
ass=3D"o">::</span><span class=3D"n">endl</span><span class=3D"p">;</span><=
/div><div class=3D"line" id=3D"LC94"><span class=3D"p">}</span></div></pre>=
<br>The global idea is that contract will inherit directly from Foo is NDEB=
UG is defined, and will inherit from make_contract<Foo> in debug mode=
..<br>Here are the declarations of contract and make_contract:<br><br><pre s=
tyle=3D"margin-left: 40px;"><div class=3D"line" id=3D"LC46"><span class=3D"=
n">template</span><span class=3D"o"><</span><span class=3D"kr">typename<=
/span> <span class=3D"n">T</span><span class=3D"o">></span></div><div cl=
ass=3D"line" id=3D"LC48"><span class=3D"k">struct</span> <span class=3D"n">=
make_contract</span><span class=3D"p">;</span><br><br></div><div class=3D"l=
ine" id=3D"LC49"><span class=3D"n">template</span><span class=3D"o"><</s=
pan><span class=3D"kr">typename</span> <span class=3D"n">T</span><span clas=
s=3D"o">></span></div><div class=3D"line" id=3D"LC50"><span class=3D"k">=
struct</span> <span class=3D"n">contract</span><span class=3D"o">:<br>#ifnd=
ef NDEBUG<br> make_contract<T><br>#else<br> T<br>#endif<br></sp=
an></div><div class=3D"line" id=3D"LC56"><span class=3D"p">{</span></div>#i=
fndef NDEBUG<br> using make_contract<T>::make_contract;<br>#else<b=
r> using T::T;<br>#endif<br><div class=3D"line" id=3D"LC65"><span class=
=3D"p">};</span></div></pre><br>That's only an idea, not a real proposal in=
any way. Here are the questions I want to raise:<br><ul><li>Do we want to =
separate such concerns?</li><li>[preconditions and postconditions do not ne=
ed to know the internals of a function]<br></li><li>Is this particualr desi=
gn flawed by nature?<br></li></ul></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_393_32434552.1394185233289--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Fri, 7 Mar 2014 18:09:49 -0500
Raw View
--089e01160478c8283804f40c5939
Content-Type: text/plain; charset=ISO-8859-1
On Fri, Mar 7, 2014 at 4:40 AM, <morwenn29@gmail.com> wrote:
> I was reading the latest paper about preconditions for the C++ programming
> languages and it reminded me of some courses I had about aspect programming
> and separation of concerns.
>
> ...code...
> That's only an idea, not a real proposal in any way. Here are the
> questions I want to raise:
>
> - Do we want to separate such concerns?
> - [preconditions and postconditions do not need to know the internals
> of a function]
> - Is this particualr design flawed by nature?
>
>
I love "separation of concerns". It is probably me number one guideline in
programming.
I don't think _these_ concerns - a function and its contract - should be
separated.
Yes, _implementation_ should be separated. But not declaration and
contract. ie think of your Foo struct without inline implementation:
struct Foo
{
static unsigned sum(unsigned a, unsigned b);
static double sqrt(double a);
static double bar(int a);
};
Where are the contracts in that interface? They should be right there -
the contract is part of the interface.
I'd prefer something like (with made up syntax):
struct FooContract
{
static unsigned sum(unsigned a, unsigned b) [[postcondition: res >=
a+ b ]];
static double sqrt(double a) [[precondition: a >= 0 ]];
static double bar(int a);
};
and then:
struct Foo : FooContract
{
....
}
ie "this class implements this contract". Not "here's a class... and over
there is its contract".
Maybe you could use your template ideas to turn your relationships around?
I currently think what you have is somewhat backwards.
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e01160478c8283804f40c5939
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><br><div class=3D"gmail=
_quote">On Fri, Mar 7, 2014 at 4:40 AM, <span dir=3D"ltr"><<a href=3D"m=
ailto:morwenn29@gmail.com" target=3D"_blank">morwenn29@gmail.com</a>></s=
pan> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">I was re=
ading the latest paper about preconditions for the C++ programming language=
s and it reminded me of some courses I had about aspect programming and sep=
aration of concerns.<br>
<br></div></blockquote><div>...code...<br>=A0<br></div><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(2=
04,204,204);padding-left:1ex"><div dir=3D"ltr">That's only an idea, not=
a real proposal in any way. Here are the questions I want to raise:<br>
<ul><li>Do we want to separate such concerns?</li><li>[preconditions and po=
stconditions do not need to know the internals of a function]<br></li><li>I=
s this particualr design flawed by nature?<span class=3D""><font color=3D"#=
888888"><br>
</font></span></li></ul></div><span class=3D""><font color=3D"#888888">
<p></p></font></span></blockquote><div><br><div><br></div><div>I love "=
;separation of concerns".=A0 It is probably me number one guideline in=
programming.<br></div><div>I don't think _these_ concerns - a function=
and its contract - should be separated.<br>
<br></div><div>Yes, _implementation_ should be separated.=A0 But not declar=
ation and contract.=A0 ie think of your Foo struct without inline implement=
ation:<br><br><div><span>struct</span> <span>Foo</span></div><div><span>{</=
span></div>
<div>=A0=A0=A0=A0<span>static</span> unsigned <span>sum</span><span>(</span=
><span>unsigned</span> <span>a</span><span>,</span> <span>unsigned</span> <=
span>b</span><span>);</span></div>=A0=A0=A0 <span>static</span> double<span=
></span> <span>sqrt</span><span>(</span><span>double</span> <span>a</span><=
span>);<br>
</span>=A0=A0=A0 <span>static</span> <span>double</span> <span>bar</span><s=
pan>(</span><span>int</span> <span>a</span><span>);</span><span><br>};</spa=
n><br></div><br></div><div>Where are the contracts in that interface?=A0 Th=
ey should be right there - the contract is part of the interface.<br>
<br></div><div>I'd prefer something like (with made up syntax):<br><br>=
<div><span>struct</span> <span>FooContract</span></div><div><span>{</span><=
/div><div>=A0=A0=A0=A0<span>static</span> unsigned <span>sum</span><span>(<=
/span><span>unsigned</span> <span>a</span><span>,</span> <span>unsigned</sp=
an> <span>b</span><span>)=A0=A0=A0 [[postcondition: res >=3D a+ b ]];<br=
>
<br></span></div>=A0=A0=A0 <span>static</span> double<span></span> <span>sq=
rt</span><span>(</span><span>double</span> <span>a</span><span>)=A0 [[preco=
ndition: a >=3D 0 ]];<br></span><br>=A0=A0=A0 <span>static</span> <span>=
double</span> <span>bar</span><span>(</span><span>int</span> <span>a</span>=
<span>);</span><span><br>
};</span><br><br></div><div>and then:<br></div><div><br>struct Foo : FooCon=
tract<br>{<br>...<br>}<br><br></div><div>ie "this class implements thi=
s contract".=A0 Not "here's a class... and over there is its =
contract".<br>
<br></div></div>Maybe you could use your template ideas to turn your relati=
onships around?=A0 I currently think what you have is somewhat backwards.<b=
r></div><div class=3D"gmail_extra">Tony<br><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e01160478c8283804f40c5939--
.