Changes between Version 48 and Version 49 of BestPracticeHandbook


Ignore:
Timestamp:
Jun 22, 2015, 2:44:38 PM (7 years ago)
Author:
Niall Douglas
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • BestPracticeHandbook

    v48 v49  
    107107
    108108
     109[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/strongly-consider-using-git,link=https://muut.com/cppbestpractice/#!/strongly-consider-using-git,alt=Comments)]]
     110
     111
    109112== 2. COUPLING: Strongly consider versioning your library's namespace using inline namespaces and requesting users to alias a versioned namespace instead of using it directly ==
    110113
     
    220223
    221224
     225[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/strongly-consider-versionin,link=https://muut.com/cppbestpractice/#!/strongly-consider-versionin,alt=Comments)]]
     226
     227
    222228== 3. PORTABILITY: Strongly consider trying your library on Microsoft Visual Studio 2015 ==
    223229
     
    243249
    244250
     251[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/strongly-consider-trying-yo,link=https://muut.com/cppbestpractice/#!/strongly-consider-trying-yo,alt=Comments)]]
     252
     253
    245254== 4. QUALITY: Strongly consider using free CI per-commit testing, even if you have a private CI ==
    246255
     
    2702792. Other free tooling such as [https://coveralls.io/ Coveralls.io] have built in integration for github and travis. Hooking Jenkins into Coveralls isn't hard, but it "just works" with Travis instead and that's a similar pattern with most free tooling which consumes CI results.
    2712803. Future tooling by Boost which dashboards Boost libraries and/or ranks libraries by a quality score will almost certainly automate on Travis and Appveyor being queryable by their RESTful APIs. In other words, placing your library in Github and adding Travis and Appveyor CI support has the highest chance of working immediately with any future Boost tooling with minimal additional effort by you.
     281
     282
     283[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/strongly-consider-using-fre,link=https://muut.com/cppbestpractice/#!/strongly-consider-using-fre,alt=Comments)]]
    272284
    273285
     
    308320scan-build will run the static analyser and generate a HTML report of the issues found with a pretty graphical display of the logic followed by the analyser into the $REPORTS directory. Jenkins has a plugin which can publish this HTML report for you per build, for other CIs you'll need to copy the generated files onto a website somewhere e.g. committing them to your repo under gh-pages and pushing them back to github.
    309321
     322
     323[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/strongly-consider-per-commi,link=https://muut.com/cppbestpractice/#!/strongly-consider-per-commi,alt=Comments)]]
     324
     325
    310326== 6. QUALITY/SAFETY: Strongly consider running a per-commit pass of your unit tests under both valgrind and the runtime sanitisers ==
    311327
     
    334350
    335351
     352[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/strongly-consider-running-a,link=https://muut.com/cppbestpractice/#!/strongly-consider-running-a,alt=Comments)]]
     353
     354
    336355== 7. SAFETY: Strongly consider a nightly or weekly input fuzz automated test if your library is able to accept untrusted input ==
    337356
     
    341360
    342361One of the most promising new input fuzz testing tools going into the long term is LLVM's fuzz testing facilities which are summarised at http://llvm.org/docs/LibFuzzer.html as they make use of the clang sanitiser coverage recording facility to additionally find the code paths least covered, plus the tool is very fast compared to afl.
     362
     363
     364[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/strongly-consider-a-nightly,link=https://muut.com/cppbestpractice/#!/strongly-consider-a-nightly,alt=Comments)]]
    343365
    344366
     
    509531
    510532
     533[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/strongly-consider-using-con,link=https://muut.com/cppbestpractice/#!/strongly-consider-using-con,alt=Comments)]]
     534
     535
    511536== 9. MAINTENANCE: Consider making it possible to use an XML outputting unit testing framework, even if not enabled by default ==
    512537
     
    589614
    590615
     616[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/consider-making-it-possible,link=https://muut.com/cppbestpractice/#!/consider-making-it-possible,alt=Comments)]]
     617
     618
    591619== 10. DESIGN/QUALITY: Consider breaking up your testing into per-commit CI testing, 24 hour soak testing, and parameter fuzz testing ==
    592620
     
    602630
    603631Regarding parameter fuzz testing, there are a number of tools available for C++, some better or more appropriate to your use case than others. The classic is of course http://ispras.linuxbase.org/index.php/API_Sanity_Autotest, though you'll need [http://ispras.linuxbase.org/index.php/ABI_Compliance_Checker their ABI Compliance Checker] working properly first which has become much easier for C++ 11 code since they recently added GCC 4.8 support (note that GCC 4.8 still has incomplete C++ 14 support). You should combine this with an executable built with, as a minimum, [http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation the address and undefined behaviour sanitisers]. I haven't played with this tool yet with Boost.AFIO, though it is very high on my todo list as I have very little unit testing in AFIO (only functional and integration testing), and fuzz testing of my internal routines would be an excellent way of implementing comprehensive exception safety testing which I am also missing (and feel highly unmotivated to implement by hand).
     632
     633
     634[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/consider-breaking-up-your-t,link=https://muut.com/cppbestpractice/#!/consider-breaking-up-your-t,alt=Comments)]]
    604635
    605636
     
    676707
    677708
     709[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/consider-not-doing-compiler,link=https://muut.com/cppbestpractice/#!/consider-not-doing-compiler,alt=Comments)]]
     710
     711
    678712== 12. CONVENIENCE: Consider having Travis send your unit test code coverage results to Coveralls.io ==
    679713
     
    754788This manually invokes gcov to convert the gcda files into a unified coverage dataset. I then use egrep to include all and egrep -v to exclude anything matching the pattern which is all the stuff not in the actual AFIO library. You'll note I build a JSON fragment as I go into the coverage.json temporary file, and the coverage is generated by chopping up the per line information into a very long string matching the coveralls JSON specification as per its API docs. Do note the separate bit of python called to convert the C++ source code into encoded JSON text (https://github.com/BoostGSoC13/boost.afio/blob/master/test/json_encode.py), I had some problems with UTF-8 in my source code, and forcing them through a ISO-8859 JSON string encode made coveralls happy. I then push the JSON to coveralls using curl. All in all a very blunt instrument, and essentially doing exactly the same thing as the official C++ coveralls tool now does, but you may find the manual method useful if the official tool proves too inflexible for your needs.
    755789
     790
     791[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/consider-having-travis-send,link=https://muut.com/cppbestpractice/#!/consider-having-travis-send,alt=Comments)]]
     792
     793
    756794== 13. CONVENIENCE: Consider creating a status dashboard for your library with everything you need to know shown in one place ==
    757795
     
    775813
    776814
     815[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/consider-creating-a-status,link=https://muut.com/cppbestpractice/#!/consider-creating-a-status,alt=Comments)]]
     816
    777817
    778818== 14. USER FRIENDLINESS: Consider letting potential users try your library with a single mouse click ==
     
    781821
    782822
    783 [[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/consider-letting-potential,link=https://muut.com/cppbestpractice/#!/consider-letting-potential)]]
     823[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/consider-letting-potential,link=https://muut.com/cppbestpractice/#!/consider-letting-potential,alt=Comments)]]
    784824
    785825== 15. DESIGN: Consider making (more) use of ADL C++ namespace composure as a design pattern ==
     
    928968
    929969The above pattern is in fact entirely C++ 03 code and uses no C++ 11. However, template aliasing in C++ 11 makes the above pattern much more flexible. Have a look at https://github.com/ptal/expected/blob/master/include/boost/functional/monads/rebindable.hpp for examples of this ADL invoked namespace composure design pattern.
     970
     971
     972[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/consider-making-use-of-adl,link=https://muut.com/cppbestpractice/#!/consider-making-use-of-adl,alt=Comments)]]
    930973
    931974
     
    10671110
    10681111 If you think of "C++ Modules" as really a somewhat more flexible and reusable implementation of existing precompiled headers which lets the compiler figure out what precompiled parts to use without you manually telling it as you must right now, you can estimate whether it is worth the effort to add support for Modules to your library as the speedup is likely similar to a precompiled header. The clang method is non-intrusive to your source code and doesn't get in the way of older compilers, but adds significant hassle in keeping the module map and the source code in sync. The Microsoft method seems to require a fair bit of #ifdef, but the module specification must be part of the source code which may aid keeping it in sync.
     1112
     1113
     1114[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/consider-defaulting-to-head,link=https://muut.com/cppbestpractice/#!/consider-defaulting-to-head,alt=Comments)]]
    10691115
    10701116
     
    12401286 In other words, you can reset the configuration macros and reinclude afio.hpp to generate a new configuration of AFIO as many times as you like within the same translation unit. This allows header only library A to require a different configuration of AFIO than header only library B, and it all "just works". As APIBind is currently lacking documentation, I'd suggest you [https://docs.google.com/presentation/d/1badtN7A4lMzDl5i098SHKvlWsQY-tsVcutpq_UlRmFI/pub?start=false&loop=false&delayms=3000 review the C++ Now 2015 slides on the topic] until proper documentation turns up. The procedure is not hard, and you can examine https://github.com/BoostGSoC13/boost.afio/blob/master/include/boost/afio/config.hpp for a working example of it in action. Do watch out for the comments marking the stanzas which are automatically generated by scripting tools in APIBind, writing those by hand would be tedious.
    12411287
     1288
     1289[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/consider-allowing-your-libr,link=https://muut.com/cppbestpractice/#!/consider-allowing-your-libr,alt=Comments)]]
     1290
     1291
    12421292== 18. FUTURE PROOFING: Consider being C++ resumable function ready ==
    12431293
     
    15141564
    15151565
     1566[[Image(http://www.nedprod.com/feed/MuutBadge.php?path=/cppbestpractice/consider-being-c-resumabl,link=https://muut.com/cppbestpractice/#!/consider-being-c-resumabl,alt=Comments)]]
     1567
     1568
    15161569== 19. Stuff still being pondered for recommendation here ==
    15171570