Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove boost and CMake from C++ requirements #1758

Closed
TheBuzzSaw opened this issue Sep 23, 2014 · 19 comments
Closed

Remove boost and CMake from C++ requirements #1758

TheBuzzSaw opened this issue Sep 23, 2014 · 19 comments

Comments

@TheBuzzSaw
Copy link

I'm actually a seasoned programmer who wanted to dabble with this program. I like solving problems, and I wanted to see if these were good for introducing to others.

Forgive my bluntness: why on earth are you using CMake + boost? They are both fantastic tools, but they are extreme overkill for these programming exercises. Is the intent to teach prospect C++ programmers to use these tools in addition to teaching them to program? If yes, I think they ought to be deferred to a later lesson. If not, there are way simpler ways to set this up.

Install GCC. (Install MinGW. Add to PATH.) Run simple build script or batch file. Why add all of boost for a few unit test helpers?

@Orangebeardo
Copy link

I had the exact same issue here. I posted a topic here two hours ago, asking for help with the C++ demo, and was told that it is not an exercise for C++ beginners, which seems to me like that's the whole point of a demo :/

I thought the purpose of exercise was to teach programming from the basics, with increasing difficulty as you progress. Why on earth start somewhere in the middle for C++?

Edit: Their C++ help pages states the following as sort of an explanation of why they're using boost, I guess:

"The unit tests use Boost.Test, the unit testing framework included with Boost. You may find other libraries in Boost useful to you as you work through the exercises. In particular, gcc 4.8 does not have a proper implementation of the standard regular expression library, but you can find a compatible library in Boost."

@TheBuzzSaw
Copy link
Author

The unit test library is wholly unnecessary. What's wrong with a simple function that compares expected output to actual output?

How early on is regex introduced? I'd just as soon tear out those chapters than maintain boost as a requirement.

@EricRFMA
Copy link

I'll second the suggestion to remove cmake. I'm having build problems and it's very hard to track them down unless you're a cmake expert. Which I'm not.

@cdaragorn
Copy link

These 2 requirements are honestly insane for something that is meant to help teach people who are in the early stages of programming/software engineering.

I love the idea of a site that helps people learn good design and engineering principles through practice, but these libraries are difficult to setup and are not necessary for simpler programs. I've used both many times before, and I love boost, it's just a lot to ask of someone who just wants some feedback and good advice.

@TheBuzzSaw
Copy link
Author

@EricRFMA
Copy link

I sorry, Mr. BuzzSaw, but that's way too complex! 😉
I also just discovered on the Mac I have to specify -stdlib=libc++ or else certain C++ 11 features aren't noticed.

@TheBuzzSaw
Copy link
Author

Is that in addition to -std=c++11 ?

@EricRFMA
Copy link

Yep

@Orangebeardo
Copy link

Are those config parameters you have to set in Exercism?

@kytrinyx
Copy link
Member

@LegalizeAdulthood - would you ping the various people who have a vested interest in this discussion?

@LegalizeAdulthood
Copy link

I made the choice to use CMake and Boost.

Let's start with CMake. When I have taught C++ programming exercise classes in the past, people spend 45 minutes just getting their build setup. That's all wasted time not spent learning anything about C++ and fighting with things that are completely irrelevant to the language.

When I did a repeat of the exact same exercise using a canned cmake recipe, we were over the build setup in 5 minutes and on to learning about the topic at hand: C++.

This is the first feedback that anyone has had problems with CMake. However, I can't improve the recipe or the instructions without knowing the specifics what what problem you had. I have tested the recipe given on linux and Windows and another contributor tested on MacOS and verified the recipe worked properly there.

If I jettison CMake, then I have to provide instructions for how to make projects and builds in Visual Studio, Xcode, CodeLite, Eclipse CDT, CLion, Unix Makefiles, plus whatever other IDE people might like to use. This makes for a laborious setup and very, very long setup instructions most of which aren't relevant to any one user. Plus you will need to modify/repeat this process for every exercise. Given that the early exercises can take somewhere between 15-20 minutes to satisfy, I don't think it's a good bootstrap experience to have people spending 45 minutes frustrated with how to setup a build. I wish more people were familiar with how to do these things, but in my testing with existing C++ programmers (not newbies), it was taking them much longer than I expected.

That a single CMake recipe can generate a build for all these environments, plus others makes CMake a win. That the CMake recipe can take care if this in a matter of under 5 minutes makes it a clear win.

More and more cross-platform IDEs (such as CLion) are choosing CMake as their project system. You may have your favorite build system, and over the decades I have used plenty, but for better or worse CMake is pulling ahead of the pack and displacing other build systems. I think this because CMake leverages the strength of your IDE while still giving you a portable build recipe, letting different members of your team/organization/community use the IDE they find comfortable while all sharing the same master build specification. No other build system I know comes anywhere close to this. I think having good IDE support with a canned build recipe is important for new C++ programmers in exercism, otherwise you're asking them to learn two languages at the same time: C++ and the cryptic world of make.

The second issue is why use boost. First, a testing framework is needed. At every company where I'ved worked at for the past 15 years, there has been a long drawn-out debate about which unit testing framework to use. If boost were only the unit testing framework, then I would probably have chosen google test instead, but boost is much more than that.

So, let's talk about the testing framework first. I am not going to write yet-another-unit-test-framework. There are too many unit testing frameworks for C++ already. So, it is wiser to use an existing one whereby people can get experience with a real unit testing framework. There are a ton of unit testing frameworks for JavaScript, but that language track chose to use jasmine-node and node.js in order to write tests on pure JavaScript that don't rely on browsers and all the inconsistencies that can bring. This is a very reasonable choice for JavaScript, but it brings along some dependencies on node.js and jasmine-node.

The situation for C++ is similar. We should not invent our own testing framework and we should pick something which is widely used. You could argue that Boost.Test has weak documentation, but I am authoring replacement documentation to remedy that problem and links to that improved documentation are provided in the getting started page. Many of the exercises need to compare collections and Boost.Test has facilities for that as well as testing whether or not an expression throws an expected exception. The collection assertions come up early in some of the exercises like prime factors. Exceptions show up in a few exercises so far where the problem states that certain invalid inputs should result in some sort of error indication, for which the language provided mechanism in C++ is exceptions.

Next, let's talk about why bring in the rest of boost. First, there is the lack of a comformant regex library in the existing C++11 support in gcc, so we'll want boost.regex to get support for regular expressions. This shows up in one of the exercises so far.

Second, the existing C++ standard library has gained many components directly from boost. There is no other such collection of libraries that can make anywhere near the same claim. Investing time in understanding more commonly used components from boost can give you a leg up on components that make it into the standard library. std::shared_ptr<T>, std::unique_ptr<T>, std::chrono, and std::thread are all examples of components in the standard library that had their origins in boost. The filesystem library is also well on the way to becoming part of the standard library.

Third, some of the problems assume that the language has built in types for manipulating calendar dates and times. C++ has no such built-in type, so we use types from boost to handle these problems in a natural manner. The focus of the exercise is to perform a date computation to achieve a result in the problem domain, not implement date computation as a utility.

Finally, as we develop more advanced problems that are more specific to the programming capabilities of C++ -- type functions, simpler forms of template meta programming, generic programming -- you will want to leverage more and more of the foundation libraries in boost to avoid having to implement lots of boilerplate yourself. Simply put, boost allows you to program at a higher level of abstraction. To my way of thinking, asking to remove boost from the C++ language track is akin to asking the C# programmers to remove the .NET framework from their language track.

I think the real issue that needs to be addressed here is not to gut the core of the language track's support, but to address whatever specific problems people have had with CMake.

Please open issues with the specific CMake problems that you are having so that they can be addressed and remedied in either the stock CMake build recipe used or in the instructions.

@TheBuzzSaw
Copy link
Author

I'm not entirely sure you understood my original issue. I'm sorry that you decided to dump a dissertation into why CMake and boost are so wonderful. If you see my original comment, I specifically mentioned that CMake and boost are great things. My question is this: why are they being used as the baseline for solving little programming problems? Personally, I am quite comfortable with using CMake and boost. However, if I am trying to teach someone to program, I am going to familiarize them with the command line and a few really basic build commands.

This is the first feedback that anyone has had problems with CMake. However, I can't improve the recipe or the instructions without knowing the specifics what what problem you had. I have tested the recipe given on linux and Windows and another contributor tested on MacOS and verified the recipe worked properly there.

I'm not having problems with CMake. I'm saying you're partially insane for inflicting it upon C++ padawans.

If I jettison CMake, then I have to provide instructions for how to make projects and builds in Visual Studio, Xcode, CodeLite, Eclipse CDT, CLion, Unix Makefiles, plus whatever other IDE people might like to use.

Or you can provide a one line build script in BASH and Batch formats. Again, who is the target audience? Just have them use GCC or Clang. I doubt the acolyte has a deeply favorite IDE already.

The second issue is why use boost. First, a testing framework is needed. At every company where I'ved worked at for the past 15 years, there has been a long drawn-out debate about which unit testing framework to use. If boost were only the unit testing framework, then I would probably have chosen google test instead, but boost is much more than that.

A "testing framework"? Really? How extensive do the tests become? I'll admit I'm basing it off the first exercise that landed in my queue: teach bob how to respond to things. The testing is nothing more than simple assertions that the strings are equal. The issue is not whether boost does a good job of this; the issue is that it imports a huge dependency for very little gain.

Next, let's talk about why bring in the rest of boost. First, there is the lack of a comformant regex library in the existing C++11 support in gcc, so we'll want boost.regex to get support for regular expressions. This shows up in one of the exercises so far.

Does the exercise require use of the parts of regex that fail to conform?

Third, some of the problems assume that the language has built in types for manipulating calendar dates and times. C++ has no such built-in type, so we use types from boost to handle these problems in a natural manner. The focus of the exercise is to perform a date computation to achieve a result in the problem domain, not implement date computation as a utility.

Fair enough. As I mentioned in my first comment, I still think boost should be introduced only when it is needed.

Finally, as we develop more advanced problems that are more specific to the programming capabilities of C++ -- type functions, simpler forms of template meta programming, generic programming -- you will want to leverage more and more of the foundation libraries in boost to avoid having to implement lots of boilerplate yourself. Simply put, boost allows you to program at a higher level of abstraction. To my way of thinking, asking to remove boost from the C++ language track is akin to asking the C# programmers to remove the .NET framework from their language track.

I disagree. C++ is meant to solve different problems than C#. C++ has a standard library. It may not have everything .NET has, but that isn't the point. I guess this pushes the discussion higher than just this issue: is the goal to teach "programming" or to teach C++? I see that people may solve the problems in whichever language they choose, but if certain languages need whole build systems and external libraries to level out, perhaps they shouldn't be candidates for solving "the same problem". That's just me.

I think the real issue that needs to be addressed here is not to gut the core of the language track's support, but to address whatever specific problems people have had with CMake.

I know how to use CMake. I was more bothered by the fact that this teaching tool asks people to install two outside dependencies. I'm merely proposing that they be dropped for the problems that do not need them. Until that time, I cannot really recommend exercism to anyone learning C++.

@LegalizeAdulthood
Copy link

Many language tracks have additional dependencies beyond the raw language compiler/interpreter. JavaScript depends on Node.js and jasmine-node being installed, C# depends on NUnit and NuGet, Clojure requires Java and Leiningen and possibly homebrew, etc. It's not like C++ is sticking out like a sore thumb in this regard.

The question was asked why CMake and Boost were included as part of the language track. I endeavoured to answer that question. My choices were made based on experience with teaching students test-driven development in C++ in a tutorial setting. I did two practice runs of this course (without CMake and with CMake) before delivering it at C++ Now! 2014.

If it were a simple matter of providing small batch scripts to compile C++ programs, then we wouldn't need build systems. Already a bug has been filed that particular versions of MacOS X need extra command-line arguments in order to properly compile with C++11 library support. Special flags need to be added if the compiler is gcc or clang. Special flags need to be added to direct the compiler and linker where to find boost. The flags that tell the compiler/linker where to find boost need to be filled out with paths that are specific to the user's system, so they can't be stock distributed to every user. Windows has a completely different set of flags than either gcc/clang and on a Windows system we can't even assume that the compiler is in the PATH when you open a command-line prompt.

Things continue to get even more complicated as you try to use regex support and find out that gcc just doesn't have it. It's not a matter of portions of it being non-conforming it is simply missing entirely. They're working on it and eventually that problem will be solved, but for now it's a problem.

Instructing the student to run a single CMake command that gives them a nicely fleshed out IDE project is much easier to get started than trying to provide all the magic variant build scripts. In the end, you end up making a more fragile version of CMake because you need to solve all the same problems that CMake solves.

I sprinkled comments through the CMakeLists.txt file in case any students are interested in what it does, but no, the point is not to teach them CMake. They don't need to know cmake in order to do the exercise. You run the command and poof your build environment is setup. From that point on all you need to know is how to run a build. That's either available blatantly in your IDE by clicking the Build button or it's typing make.

@TheBuzzSaw
Copy link
Author

You do what you feel is right. :)

My opinion of the "best" approach is what was done at my university. The choice of environment/IDE was irrelevant because each problem was submitted as a single .cpp file. Often, the assignment included stubs (or just like in this case: a test suite that had to be passed). I could work on the problem in whatever I wanted. I just had to submit the .cpp file back at the end.

I guess I'm just thrown off that I'm being handed any kind of build/make/project file at all. You are not responsible for that aspect. Let each developer handle his/her own environment. Voila! You support every environment out there! And I don't have to install CMake! If someone is truly starting from scratch, include simple instructions for setting up a basic environment.

@cdaragorn
Copy link

Javascript depends on Node.js? Really? C# requires NUnit and NuGet? I think your definition of depends and requires are a bit off. None of those libraries are required or even remotely needed to accomplish anything in either of those languages.

The point I see here is simply that by requiring such complex dependencies, you're making this difficult at best and impossible at worst for beginners. C++ does NOT require either of these to do a ton of very useful things with it. I see no reason why these requirements should be there for every test. There's no reason why more advanced tests can't require them, but it rules out any test geared at beginners.

@LegalizeAdulthood
Copy link

@cdaragorn Yes, the language tracks in exercism for JavaScript require Node.js and jasmine, etc., as stated in the linked "getting started with ..." pages on the exercism help site

@TheBuzzSaw I tried your approach for my workshop and these were seasoned C++ developers, not people with only a basic familiarity with syntax and maybe a few exercises under their belt. I scheduled 3 hours for the workshop and the first 45 minutes (minimum) were spent setting up "simple build scripts" for exactly the same sort of thing that exercism is doing: unit tests + implementation. I was expecting that their proficiency with their own preferred build system (Xcode, VS, Makefiles, whatever) was going to get them going in 5-10 minutes. It took much, much longer. My choice of a "run it and forget it" canned CMake recipe was based on experience of teaching classes with seasoned developers. When I did another test run with the CMake recipe, we were through that phase in 5-10 minutes with a novice programmer. That's less time than it would take me to verbally explain the steps they would need to go through in VS to setup their solution. With the final version at the conference, CMake got us through the initial setup in about 10-15 minutes.

@TheBuzzSaw
Copy link
Author

K. So CMake is great for teaching a classroom of people who lied about being proficient with a particular environment. I don't agree with it here, but I can't really argue with your experience in that particular setting.

What about boost? Could it at least be dropped for problems that don't need it? Please don't cite the unit test framework again.

void Test(const char* expected, const char* actual)
{
    if (strcmp(expected, actual))
        printf("ERROR! Expected (%s). Actual (%s).\n", expected, actual);
    else
        printf("Passed!");
}

We're not doing "unit tests". We're simply informing the user about whether they coded it right. Pulling in all of boost is silly to me.

@LegalizeAdulthood
Copy link

Going down that road means you're re-implementing a unit test framework one exercise at a time. Seriously. Been there, done that. For languages that don't ship with a unit test framework, every other language track has you get the unit test framework to use with the language track.

@TheBuzzSaw
Copy link
Author

If you say so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants