3

According to Should we avoid language features that C++ has but Java doesn't?, I know it is horrible to write C++ as if Java, mostly because it drops the beneficial features of C++ languages.

But responding to the point 2 in this question:

C++ code with C++ specific features (e.g.: friend functions, multiple inheritance) can only be maintained or reviewed by C++ programmers, but if we just write C++ like Java (without C++ language specific feature), the code can be maintained or reviewed by both C++ and Java programmers.

I found it seems the following questions supports the statement above:

Is it effective to review code in language I don't know?

Should Junior Programmers be involved as code reviewers in the projects of Senior Programmers?

I think they seems support this point:

1.It allows more people (Java programmers) to review my C++ code

2.It allows Java programmers to learn C++ easier during reviewing my c++ code

I mean I'm not in extreme cases that dropping all C++ features, but I would prefer not using C++ features if the substitutes is not complex, for example, I would not write all C++ classes in .h like a single .java file:

class A{
private:
  int b;
  void methodC(){
    //some other code
  }
}

because separating .h and .cpp is easy for C++ newbies. But I would avoid C++ features if the C++ feature can easily be replaced by a pseudo code both for C++ and Java, for example: multiple inheritance, which can be replace by composition + multiple interface.

So My question is, is "letting more people(e.g.:Java programmers) to review my code" a reason to "write C++ like Java" at some degree?

ocomfd
  • 5,652
  • 8
  • 29
  • 37
  • 7
    Why is it important to have more people reviewing your code? Will the review be more helpful if you have 20 reviewers rather than 2? As the top ranked answers to your linked question explain, it can be very useful to have team members new to a language participate in a code review *as a teaching tool*. – Charles E. Grant Jun 07 '18 at 02:56
  • 3
    In Java `Foo foo = new Foo();` is how you make an instance of `Foo`. In C++, it is a type error – Caleth Jun 07 '18 at 08:10
  • In Java, you define an interface with the keyword `interface`, an abstract class with the keywords `abstract class` and a concrete class with `class`. In C++ *all three* use *either* `class` or `struct` – Caleth Jun 07 '18 at 08:16
  • 14
    Why write C++ code in the first place if available programmers only know Java? – mouviciel Jun 07 '18 at 09:55
  • The answer (the merit of this suggestion) would have been in the details. Projects (and companies and teams) have code standard and style guides. Typically, projects also have substantial amount of code; such code serve as learning materials for new developers to imitate. If the code base is bad, it is insane to expect new code contributed by fresh programmers to be substantially better than the old ones. The merit of getting help from Java programmers depends on whether your project or work environment has a higher number of (politically powerful) Java programmers that won't let C++ live. – rwong Jun 07 '18 at 10:26
  • 2
    And again, downvotes from people who obviously didn't understand that downvotes are for bad questions, not for bad ideas. – Doc Brown Jun 07 '18 at 21:12
  • 1
    Difference between a programmer and developer is ceasing the opportunity to learn and grow. How do you becoe a better programmer and get better results if you stick to doing the same things the same way despite using a different language. If its supposed to be a C++ program, write a C++ program and the reviewers will become better programmers. Writing "A C++ syntax Java Program" does no one any favors. – mattnz Jun 08 '18 at 09:00
  • 1
    My own experience is that Java reviewers won't provide any value above C++ reviewers, and you will wind up with massive confusion. They are far too different. C++ developers tend to be more detail and performance oriented, and can actually read the code correctly. Don't force a square peg into a round hole. – Frank Hileman Jun 08 '18 at 22:42
  • I've seen C++ programs using hundreds of #defines to make them look like Pascal (e.g. #define BEGIN { ). Doesn't make it a good idea :) – jwenting Jun 21 '18 at 06:02

4 Answers4

22

The whole statement "write C++ as Java" is total nonsense. You cannot write C++ as Java. If you tried, your program would leak, or crash, or both. C++ does not have garbage collection. C++ does not have proper exceptions. C++ has very different approach on parametric polymorphism.

And after all, it implies that all developers know Java.

Also, you seem to be focusing too much at review. Will the other developer be able to find and fix the bug in code? Basically, the reviews are just there to ensure that the reviewer, and supposedly, others in team, will further be able to operate the code without its author.

If you rephrase your question as "may some C++ features be avoided so that developers (at hands) can understand and edit it easier", then answer is definite "yes, of course". Most project have in their code style guides notes "we don't use ...". Actually, there are many experienced C++ developers which think that some feature does not work correctly, and should be avoided.

max630
  • 2,543
  • 1
  • 11
  • 15
  • 7
    How are exceptions in C++ not proper? – Deduplicator Jun 07 '18 at 12:10
  • 2
    The most annoying thing for me is they do not collect the stack. So the Java/C#/Python pattern "catch all at bottom event loop/request handler, write to log, keep running" is not feasible because after catch the exception it is very often not really descriptive data, which _may_ let you guess what and where happened. Instead, you have to let the program crash and then OS will collect memory dump and then you find the problematic place. And if you cannot afford crashing, your only choice is to stop throwing exceptions, or catch them as early as possible. Which defeats the whole point of them. – max630 Jun 07 '18 at 12:29
  • 11
    @max630: That kind of assumes that the way to handle exceptions is to write a call stack to a log and move on. If you're doing basically *anything else* besides that, exceptions work just fine. – Nicol Bolas Jun 07 '18 at 13:35
  • @Deduplicator: get a copy of Herb Sutter's "Exceptional C++" and read the 12 chapters about Exception-Safety issues, then you may come to the conclusion there is something wrong with exeptions in that language. – Doc Brown Jun 07 '18 at 17:11
  • @DocBrown How about giving the points from it which you deem paramount, instead of just pointing to huge parts of some offline book. – Deduplicator Jun 07 '18 at 20:46
  • 2
    @Deduplicator: the point is that one probably needs to make it through the fourty pages of those chapters of that offline book to get a complete understanding of what hidden issues C++ has when trying to implement exception-safe code in templates. – Doc Brown Jun 07 '18 at 21:08
  • @DocBrown: Not sure what's so bad there. Aside from they should add `noexcept(auto)`. – Deduplicator Jun 07 '18 at 21:53
  • @NicolBolas, what "anything else" could program do except moving on? Crash? Yes, I mentioned that option. – max630 Jun 08 '18 at 02:31
  • 6
    @max630: You specifically said "*catch all at bottom event loop/request handler*". There's no mention of recovering from the error, or figuring out how to complete the user's request based on it, or any number of alternatives that have to happen closer to the site of the exception being thrown. Most exception handling is not about logging where an exception was thrown; it's about figuring out how to move on based on what kind of exception it was. If you can't open a file, you don't log that a file couldn't be opened; you ask for a new file. There's no need to log that. – Nicol Bolas Jun 08 '18 at 02:40
  • @NicolBolas that I also mentioned, though it was challenging in the comment field. I believe this is not how exceptions designed to be used. If you "recover" from exception very close to the operation when it was thrown (most probably, just next to the statement), it does not differ from return code. And only small portion of possible exceptions are handled this way, though they may happen more often than others. – max630 Jun 08 '18 at 03:47
  • 1
    @Deduplicator: found this [one](http://www.gotw.ca/gotw/008.htm) - the problem (and solution) of creating a generic stack, with the requirement to make it exception-safe and exception-neutral. Note it took the community about 3 years(!) to find this solution, and the original stack interface had to be modifies to fulfill the requirements. – Doc Brown Jun 08 '18 at 06:05
  • @DocBrown That GotW is really outdated, consider it uses `std::uncaught_exception()`. Anyway, not actually a good argument for you, sorry. – Deduplicator Jun 08 '18 at 10:31
  • @Deduplicator: just because you found `std::uncaught_exception` somewhere below in that article (in a challenge at the end, more a side note!), does not invalidate my argument. Or do you have any evidence that writing exception-safe and exception-neutral code in C++ has become way much simpler and less error-prone over the last 20 years? – Doc Brown Jun 08 '18 at 11:08
  • @DocBrown: Do you have any evidence that it is any worse than other languages with exceptions? – Deduplicator Jun 08 '18 at 12:07
  • @Deduplicator There is a reason exceptions are avoided in many C++ codebases. You only have to talk to some C++ developers. – Frank Hileman Jun 08 '18 at 22:48
  • 2
    @FrankHileman: Name them, and we can see whether they are (in some circumstances / still / at all) justified. "Trust me, there are good reasons" is simply useless. – Deduplicator Jun 08 '18 at 23:29
11

The idea that Java programmers can review (i.e. find mistakes in) or maintain (i.e. modify) C++ code if it only uses the features that kinda look like Java is badly misguided.

The underlying execution model of C++ is different enough from Java that any such attempt will lead to bugs, pain, and in some cases expensive lawsuits from customers.

The main difficulty in switching from Java to C++ is not learning a few additional features of the language, it's understanding the execution model and idioms. Why is new in Java ubiquitous, but frowned upon in modern C++? How do you prevent memory leaks? How do you prevent use-after-free or invalidated iterators? What happens if you use an invalid index in an array, and how do you guard against that? These are the questions a C++ programmer must be able to answer, and a Java programmer just can't.

Sebastian Redl
  • 14,950
  • 7
  • 54
  • 51
  • You actually do have to worry somewhat about those things in Java. Iterators CAN indeed go bad in Java, and multithreading is a common cause of that sort of insanity. Multithreading can lead to all sorts of Fun™ errors happening. – Haakon Løtveit Jun 08 '18 at 09:58
5

It isn't feasible at all to write C++ as if it was Java: memory leaks or ownership semantics, no explicit use of pointers/references etc. Besides, whoever is reviewing your code, should be able to understand what the code is doing.

Does that mean a learning C++ developer cannot review your code? Well, they sure can, because code reviews are a great learning tool. If you use a feature of C++ that the reviewer does not know about, they can ask. These additional questions can also help you catch mistakes.

Features such as multiple inheritance should be used sparingly, but not with the goal of making it more understandable for those that are not aware of the features/syntax of the language.

Athos vk
  • 430
  • 2
  • 7
0

A very effective way to write c++ so that it is both readable and powerful is to hide expert complexity behind semantically simple interfaces.

A great example of this is std::shared_ptr<T>. Getting the implementation of a std::shared_ptr right without sacrificing performance or correctness in multi-threaded programs is not trivial.

But if your reviewer sees this code:

auto px = std::make_shared<X>();

It's pretty obvious to him that px is a pointer with shared ownership, regardless of the complexities of lock-free reference counting or type-erasure of the deleter (to name but 2).

Further, if ownership of X is always shared, then it makes sense to create a higher-level wrapper which can be treated as a value:

struct SharedX
{
    int some_x_method() { return px_->some_x_method(); }
private:
    std::shared_ptr<X> px_ = std::make_shared<X>();
}; 

Now we can write code like this:

auto x = SharedX();
do_something_with(x);

and we can't accidentally create an invalid SharedX.

If we want to be able to provide null handles, we can do that safely by demanding that the programmer specifically requests one:

struct SharedX
{
    SharedX()
    : px_(std::make_shared<X>())
    {}

    static SharedX invalidHandle() { return SharedX(nullptr); }

    int some_x_method() { 
        assert(px_);
        return px_->some_x_method(); 
    }

private:
    explicit SharedX(std::nullptr_t)
    : px_(nullptr)
    {}

private:
    std::shared_ptr<X> px_;
}; 

// create a new shared x
auto sx = SharedX();

// create an uninitialised shared x to act as a placeholder for
// some later value (eg if deserialised)
auto nsx = SharedX::invalidHandle();

Novices, Java programmers, experts and value-semantic-purists such as myself will now all be happy.

Richard Hodges
  • 227
  • 1
  • 2
  • Actually, wrapping a smart-pointer is not such a great idea, as it doesn't gain you anything but noise. You can invoke Methods of the pointee using `->` easily enough. Though if you insist, consider Just specializing `std::shared_ptr` to achieve your aims. – Deduplicator Jul 02 '18 at 16:13
  • @Deduplicator If value semantics are desired and the implementation of an object is best shared, then I would argue that wrapping the shared pointer is inevitable. I would agree that it is not always the correct design. However the motivation here is to reduce reader complexity without sacrificing the efficiency and preciseness of c++. – Richard Hodges Jul 03 '18 at 07:50