Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does it mean to make an interface programmatic instead of semantic?

Tags:

java

c++

c#

android

At the moment I am reading the book "Code Complete, 2nd Edition". In Chapter 6.2 the author talks about classes and interfaces and gives the following advice:

Make interfaces programmatic rather than semantic when possible
Each interface consists of a programmatic part and a semantic part. The programmatic part consists of the data types and other attributes of the interface that can be enforced by the compiler. The semantic part of the interface consists of the assumptions about how the interface will be used, which cannot be enforced by the compiler. The semantic interface includes considerations such as “RoutineA must be called before RoutineB” or “RoutineA will crash if dataMember1 isn’t initialized before it’s passed to RoutineA.” The semantic interface should be documented in comments, but try to keep interfaces minimally dependent on documentation. Any aspect of an interface that can’t be enforced by the compiler is an aspect that’s likely to be misused. Look for ways to convert semantic interface elements to programmatic interface elements by using Asserts or other techniques.

I understand what the author means by semantic and programmatic but what I don't understand is how you would convert a semantic interface function to a programmatic one. He mentions using asserts or other techniques to accomplish this.

Lets take the example of the author:

RoutineA must be Called before RoutineB. I am assuming these routines are part of the interface (public functions) because that is what this is about, ugly interfaces.

So if RoutineA must indeed be called before calling RoutineB, how would you reorganize this interface using asserts or other techniques?

I have some thoughts about this but I am not sure if they are correct.

Assuming both RoutineA and RoutineB are public functions, that would mean that both of them should be available independently of each other but the only restriction is that you first must call RoutineA before you can call RoutineB independently.

If this is indeed the case, then how would you solve this using asserts or other techniques?

If there is error in my assumption, feel free to correct me.

Also, I intentionally posted this under the current tags because tags like object-oriented-programming/design/interface have very little hits meaning my question would probably not be seen a lot.

like image 821
CantThinkOfAnything Avatar asked Dec 06 '25 15:12

CantThinkOfAnything


2 Answers

Two possible answers:

  • Put assert( a_called ); in routine RoutineB
  • Remove RoutineB from the interface of the class, and make RoutineA return a new object which has a RoutineB member.

In the latter case, you probably would want to make the external classes be thin wrappers around a smart pointer to an internal class, and then RoutineA would just copy the pointer.

class Impl;
class SecondClass;
class FirstClass
{
    std::shared_ptr<Impl> pimpl;
public:
    FirstClass();
    SecondClass RoutineA(...);
    ...
}

class SecondClass
{
    std::shared_ptr<Impl> pimpl;
    friend class FirstClass;
    SecondClass(const std::shared_ptr<Impl>& impl) : pimpl(impl);
public:
    void RoutineB(....);
}

SecondClass FirstClass::RoutineA(...)
{
    // Do stuff
    return SecondClass(pimpl);
}

You can also do it with a unique_ptr, but that code is a bit longer.

like image 53
Martin Bonner supports Monica Avatar answered Dec 08 '25 04:12

Martin Bonner supports Monica


I think you should check the restriction ("RoutineA must be Called before RoutineB") at run time. Programming languages in the tags cannot check such a restriction at compile time. Your code may look like:

RoutineA()
{
  aCalled = true;
  //some operations..
}
RoutineB()
{
  if(!aCalled) // or an assertion
  {
    throw NotReadyException("RoutineA must be called");
  }
  //some operations..
}
like image 23
Q Q Avatar answered Dec 08 '25 03:12

Q Q



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!