diff options
Diffstat (limited to 'ml/dlib/docs/docs/howto_contribute.xml')
-rw-r--r-- | ml/dlib/docs/docs/howto_contribute.xml | 604 |
1 files changed, 604 insertions, 0 deletions
diff --git a/ml/dlib/docs/docs/howto_contribute.xml b/ml/dlib/docs/docs/howto_contribute.xml new file mode 100644 index 000000000..3cf4a4209 --- /dev/null +++ b/ml/dlib/docs/docs/howto_contribute.xml @@ -0,0 +1,604 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?> + +<doc> + <title>How to Contribute</title> + + + + <!-- ************************************************************************* --> + + <body> + + + <!-- **************************** EASY CONTRIBUTIONS **************************** --> + + <h2>Contributing Money</h2> + + The simplest way to contribute is to donate money via Zelle or PayPal + to davis@dlib.net. Any amount is appreciated :) + + <!-- **************************** CODE CONTRIBUTIONS **************************** --> + <h2>Contributing Code</h2> + + Code contributions are welcome and can be done by submitting a pull request + to <a href="https://github.com/davisking/dlib">dlib's github page</a>. + + <p> If you want to make a big change or feature addition, it's probably a good idea to talk to me about it first. + Additionally, you should read over the coding guidelines below + and try to follow them. It is also probably a good idea to read the books Effective C++ and + More Effective C++ by Scott Meyers. + </p> + + + <h2>Coding Guidelines</h2> + + 1. <a href="#1">Use Design by Contract</a><br/> + 2. <a href="#2">Use spaces instead of tabs.</a><br/> + 3. <a href="#3">Use the standard C++ naming convention</a><br/> + 4. <a href="#4">Use RAII</a><br/> + 5. <a href="#5">Don't use pointers</a><br/> + 6. <a href="#6">Don't use #define for constants.</a><br/> + 7. <a href="#7">Don't use stack based arrays.</a><br/> + 8. <a href="#8">Use exceptions, but don't abuse them</a><br/> + 9. <a href="#9">Write portable code</a><br/> + 10. <a href="#10">Setup regression tests</a><br/> + 11. <a href="#11">Use the Boost Software License</a><br/> + + + <ul> + <!-- **************************** --> + <anchor>1</anchor> + <li> <h3> Apply Design by Contract to Your Code </h3> + <ul><p> + The most important part of a software library isn't the code, it is the set + of interfaces the library exposes to the user. These interfaces need to be easy + to use right, and hard to use wrong. The only way this + happens is if the interfaces are documented in a simple, consistent, and precise way. + </p> + <p> + The name for the way I design and document these interfaces is known as + Design by Contract. There is a lot that can be said about Design by Contract, in fact, + whole books have been written about it, and programming languages exist which + use Design by Contract as a central element. Here I will just go over some + of the basic ways it is used in dlib as well as some of the reasons why it is a + Good Thing. + </p> + <li> <b>Functions should have documented preconditions which are programmatically verifiable</b> + <ul> + <p> + Many functions have a set of requirements or preconditions that need to be satisfied + if they are to be used. If these requirements are not satisfied + when a function is called then the function will not do what it is supposed to do. Moreover, + any piece of software that calls a function but doesn't make sure all preconditions + are satisfied contains a bug, <i>by definition</i>. + </p> + <p> + This means all functions must precisely document their preconditions if they are to be + usable. In fact, all preconditions should be programmatically verifiable. Doing this + has a number of benefits. First, it means they are unambiguous. English + can be confusing and vague, but saying "<tt>some_predicate == true</tt>" uses a + formal language, C++, that we all should understand quite well. Second, it means + you can put checks into the code that will catch <i>all</i> usage errors. + </p> + <p> + These checks should always be implemented using + <a href="metaprogramming.html#DLIB_ASSERT">DLIB_ASSERT</a> or + <a href="metaprogramming.html#DLIB_CASSERT">DLIB_CASSERT</a> and they should always + cover all preconditions. + These macros take a boolean argument and if it is false they throw dlib::fatal_error. So + you can use them to check that all your preconditions are true. Also, don't forget that + a violated function precondition indicates a bug in a program. + That is, when dlib::fatal_error is thrown it means a bug has been found and the only thing + an application can do at that point is print an error message and terminate. + In fact, dlib::fatal_error has checks in it to make sure someone doesn't catch the + exception and ignore it. These checks will abruptly terminate any program that attempts + to ignore fatal errors. + </p> + <p> + The above considerations bring me to my next bit of advice. Developers new to Design by Contract + often confuse input validation requirements with function preconditions. When I tell them + to consider any violation of a function's preconditions a bug and terminate their application + with an error message they complain that this is not at all what an application should do when + it receives invalid user inputs. + + They are right, that would be a bad thing + and you should not write software that behaves that way. The way out of this problem is, of + course, to not consider invalid input as a bug. Instead, you should perform explicit input validation + on any + data coming into your program <i>before</i> it gets to any functions that have preconditions + which demand the validated inputs. Moreover, if you make your preconditions programmatically verifiable + then it should be easy to validate any inputs by simply using whatever it is you + use to check your preconditions. + </p> + <p> + Consider the function <a href="dlib/svm/svm_abstract.h.html#cross_validate_trainer">cross_validate_trainer</a> as an + example. One of its requirements is that the input forms a valid binary classification problem. + This is documented in the list of preconditions as + "<tt>is_binary_classification_problem(x,y) == true</tt>". This precondition is just saying + that when you call + the <a href="dlib/svm/svm_abstract.h.html#is_binary_classification_problem">is_binary_classification_problem</a> + function on the x and y inputs it had better return true + if you want to use those inputs with the <tt>cross_validate_trainer</tt> function. + Given this information it is trivial to perform input validation. All you have to do is + call <tt>is_binary_classification_problem</tt> on your input data and you are done. + </p> + <p> + Using the above technique you have validated your inputs, documented your preconditions, and are + buffered by DLIB_ASSERT statements that will catch you if you accidentally forget to validate any + inputs. + </p> + <p>The thing to understand here is that + a violation of a function's preconditions means you have a bug on your hands. Or in other words, + you should never intentionally violate any function preconditions. But of course + it will happen from time to time because bugs are unavoidable. But at least with + this approach you will get a detailed error message early in development rather than a + mysterious segmentation fault days or weeks later. + </p> + </ul></li> + <li> <b>Functions should have documented postconditions </b> + <ul><p> + I don't have nearly as much to say about postconditions as I did about function requirements. You should + strive to write programmatically verifiable postconditions because that makes your postconditions + more precise. However, it is sometimes the case that this isn't practical and that is fine. + But whatever you do write needs to clearly communicate to the + user what it is your function does. + </p></ul></li> + <p> + Now you may be wondering why this is called <i>Design</i> by Contract and not Documentation + by Contract. The reason is that the process of writing down all these detailed descriptions + of what your code does becomes part of how you design software. For example, often you + will find that when you go to write down the requirements for calling a function you are unable + to do so. This may be because the requirements are so complex you can't think of a way + to describe them, or you may realize that you don't even know what they are. Alternatively, + you may know what they are but discover there isn't any way to verify them programmatically. All these + things are symptoms of a bad <i>design</i> and the reason you became aware of this design problem + was by attempting to apply Design by Contract. + </p> + <p> + After you get enough practice with this way of writing software you begin to think a lot + more about questions like "how can I design this class such that every member function + has a very simple set of requirements and postconditions?" Once you start doing this + you are well on your way to creating software components that are easy to use right, and + hard to use wrong. + </p> + <p> + The notation dlib uses to document preconditions and postconditions is described in + the <a href="intro.html#Notation">introduction</a>. All code that goes into dlib + must document itself using this notation. You should also separate the implementation + and specification of a component into two separate files as described in the introduction. This + way users aren't confused or distracted by implementation details when they look at the documentation. + </p> + </ul> + </li> + + + <!-- **************************** --> + <anchor>2</anchor> + <li><h3>Use spaces instead of tabs. </h3> + <ul> <p>This is just generally good advice but + it is especially important in dlib since everything is viewable + as pretty-printed HTML. Tabs show up as 8 characters in most browsers + and this results in the HTML version being difficult to read. So + don't use tabs. Additionally, please use 4 spaces for each tab level.</p> + </ul></li> + + + + <!-- **************************** --> + <anchor>3</anchor> + <li><h3> Don't use capitol letters in the names of variables, functions, or + classes. Use the _ character to separate words. </h3> + <ul> + <p> + The reason dlib uses this style is because it is the style used by the + C++ standard library. But more importantly, dlib currently provides + an interface to users that has a consistent look and feel and it is + important to continue to do so. + </p> + <p> + As for constants, they should usually contain all upper case letters + but all lowercase is ok sometimes. + </p> + </ul></li> + + <!-- **************************** --> + <anchor>4</anchor> + <li> <h3> Don't use manual resource management. Use RAII + instead.</h3> + <ul><p> + You should not be calling new and delete in your own code. You should instead + be using objects like the std::vector, std::shared_ptr, + or any number of other objects that manage resources such as memory for you. If you want + an array use std::vector (or the checked <a href="containers.html#std_vector_c">std_vector_c</a>). + If you want to make a lookup table use a <a href="containers.html#map">map</a>. If you want + a two dimensional array use <a href="linear_algebra.html#matrix">matrix</a> or + <a href="containers.html#array2d">array2d</a>. + </p> + <p> + These container objects are examples of what is called RAII (Resource Acquisition Is Initialization) + in C++. It is essentially a name for the fact that, in C++, you can have totally automated and + deterministic resource management by always associating resource acquisition with the construction + of an object and resource release with the destruction of an object. I say resource management + here rather than memory management + because, unlike Java, RAII can be used for more than memory management. For example, when + you use a <a href="dlib/threads/threads_kernel_abstract.h.html#mutex">mutex</a> you first lock + it, do something, and then you need to remember to unlock it. The RAII way of doing this is + to use the <a href="api.html#auto_mutex">auto_mutex</a> which will lock a mutex and automatically + unlock it for you. Or suppose you have made a TCP <a href="api.html#sockets">connection</a> + to another machine and you want to be certain the resources associated with that connection + are always released. You can easily accomplish this with RAII by using the std::unique_ptr as + shown in <a href="sockstreambuf_ex.cpp.html">this</a> example program. + </p> + <p> + RAII is a trivial technique to use. All you have to do is not call new and delete and + you will never have another memory leak. Just use the appropriate <a href="containers.html">container</a> + instead. Finally, if you don't use RAII then your code is almost certainly not exception safe. + </p> + </ul> + </li> + + <!-- **************************** --> + <anchor>5</anchor> + <li> <h3>Don't use pointers </h3> + <ul><p> + There are a number of reasons to not use pointers. First, if you are using pointers then + you are probably not using RAII. Second, pointers are ambiguous. When I see a pointer + I don't know if it is a pointer to a single item, a pointer to nothing, or + a pointer to an array of who knows how many things. On the other hand, when I see a + std::vector I know with certainty that I'm dealing with a kind of array. Or if I see a + reference to something then I know I'm dealing with exactly one instance of some object. + </p> + <p> + Most importantly, it is impossible to validate the state of a pointer. Consider two + functions: + <code_box> +double compute_sum_of_array_elements(const double* array, int array_size); +double compute_sum_of_array_elements(const std::vector<double>& array); </code_box> + + The first function is inherently unsafe. If the user accidentally passes in an invalid pointer + or sets the size argument incorrectly then their program may crash and this will turn into a + potentially hard to find bug. This is because there is absolutely nothing you can do inside + the first function to tell the difference between a valid pointer and size pair and an invalid + pointer and size pair. <b><i>Nothing</i></b>. The second function has none of these difficulties. + </p> + <p> + If you absolutely need pointer semantics then you can usually use a smart pointer like + std::unique_ptr or std::shared_ptr. + If that still isn't good enough for you and you <i>really</i> need to use a normal C style pointer + then isolate your pointers inside a class or function so that they are contained in a small area of the code. + However, in practice the container classes in dlib and the STL are more than sufficient in nearly + every case where pointers would otherwise be used. + </p> + </ul> + </li> + + <!-- **************************** --> + <anchor>6</anchor> + <li> <h3> Don't use #define for constants. </h3> + <ul><p> + dlib is meant to be integrated into other people's projects. Because of this everything + in dlib is contained inside the dlib namespace to avoid naming conflicts with user's code. + #defines don't respect namespaces at all. For example, if you #define a constant called SIZE then it + will cause a conflict with any piece of code <i>anywhere</i> that contains the identifier SIZE. + This means that #define based constants must be avoided and constants should be created using the + const keyword instead. + </p> + </ul> + </li> + + <!-- **************************** --> + <anchor>7</anchor> + <li> <h3>Don't use stack based arrays. </h3> + <ul><p> + A stack based array, or C style array, is an array declared like this: + <code_box>int array[200];</code_box> + Most of my criticisms of pointers also apply to stack based arrays. In particular, + if you are passing a stack based array to a function then that means you are probably + using functions similar to the unsafe compute_sum_of_array_elements() example above. + </p> + <p> + The only time it is OK to use this kind of array is when you use it for simple + tasks and you don't start passing pointers to the array to other parts of your code. You + should also use a constant to store the array size and use that constant in your loops + rather than hard coding the size in numerous places. + </p> + <p> + But even still, you should use a container class instead and preferably one with the ability to do range + checking such as the <a href="containers.html#std_vector_c">std_vector_c</a>. </p> + <p> + Consider the following two bits of code: +<code_box> +for (int i = 0; i < array_size; ++i) + my_c_array[i] = 4; + +for (int i = 0; i < my_std_vector.size(); ++i) + my_std_vector[i] = 4; +</code_box> + The second loop clearly doesn't overflow the bounds of the my_std_vector. On the other + hand, just by looking at the code in the first loop, we can not tell if it overflows + my_c_array. We have to assume that array_size is the appropriate constant but we could be wrong. + </p> + <p> + Buffer overflows are probably the most common kind of bug in C and C++ code. These bugs also + lead to serious exploitable security holes in software. So please try to avoid stack based arrays. + </p> + </ul> + </li> + + + + <!-- **************************** --> + <anchor>8</anchor> + <li> <h3> Use exceptions, but don't abuse them. </h3> + <ul> + <p> + Exceptions are one of the great features of modern programming languages. Some + people, however, consider that to be a contentious statement. But if you accept + the notion that a software library should be hard to use wrong then it + becomes difficult to reject exceptions. + </p> + <p> + Most of the complaints I hear about exceptions are actually complaints + about their <i>misuse</i> rather than objections to the basic idea. + So before I begin to defend the above + paragraph I would like to lay out more clearly when it is appropriate to + use exceptions and when it is not. + </p> + <p> + There are two basic questions you should ask yourself when deciding whether to + throw an exception in response to some event. The first is (1) "should this event + occur in the normal use of my library component?" The second question is (2) "if this event + were to occur, is it likely that the user will want to place the code for dealing + with the event near the invocations of my library component?" + </p> + <p> + If your answers to the above two questions are "no" then you should probably + throw an exception in response to the event. On the other hand, if you answer + "yes" to either of these questions then you should probably <i>not</i> throw an exception. + </p> + + <p> + A good example of an event worth throwing exceptions for is running out of memory. + (1) It doesn't happen very often, and (2) when it does happen it is hardly ever the case that + you want to deal with the out of memory event right next to the place where you are + attempting to allocate memory. + </p> + <p> + Alternatively, an example of an event that shouldn't throw an exception comes to + us from the C++ I/O streams. This part of the standard library allows + you to read the contents of a file from disk. When you hit the end of file they + do not throw an exception. This is appropriate because (1) you usually want to + read a file in its entirety. So hitting EOF happens all the time. Additionally, (2) + when you hit EOF you usually want to break out of the loop you are in + and continue immediately into the next block of code. + </p> + <p> + Usually when someone tells me they don't like exceptions they give reasons like "they make + me put try/catch blocks all over the place and it makes the code hard to read." Or "it makes + it hard to understand the flow of a program with exceptions in it." Invariably they + have been working with bodies of software that disregard the above rules regarding questions + 1 and 2. Indeed, when exceptions are used for flow control the results are horrifying. Using + exceptions for events that occur in the normal use of a software component, especially when + the events need to be dealt with near where they happen result in a spaghetti-like mess + of throw statements and try/catch blocks. Clearly, exceptions should be used judiciously. + So please, take my advice regarding questions 1 and 2 to heart. + </p> + <p> + Now let's go back to my claim that exceptions are an important part of making + a library that is hard to use wrong. But first let's be honest about one thing, + many developers don't think very hard about error handling and they similarly aren't very + careful about checking function return codes. Moreover, even the most studious of + us can easily forget to add these checks. It is also easy to forget to add + appropriate exception catch blocks. + </p> + <p> + So what is so great about exceptions then? Well, let's imagine some error just occurred + and it caused an exception to be thrown. If you forgot to setup catch blocks to deal with + the error then your program will be aborted. Not exactly a great thing. But you will, however, + be able to easily find out what exception was thrown. Additionally, exceptions typically contain a + message telling you all about the error. Moreover, + any debugger worth its + salt will be able to show you a stack trace that lets you see exactly where the exception came from. + The exception <i>forces</i> you, the user, to + be aware of this potential error and to add a catch block to deal with it. + This is where the "hard to use wrong" comes from. + </p> + <p> + Now let's imagine that we are using return codes to communicate errors to the user and the + same error occurs. If you forgot to do all your return code checking then you will + simply be unaware of the error. Maybe your program will crash right away. But more likely, it + will continue to run for a while before crashing at some random place far away from the source + of the error. You and your debugger now get to spend a few hours of quality time + together trying to figure out what went wrong. + </p> + <p> + The above considerations are why I maintain that exceptions, when used properly, contribute to + the "hard to use wrong" factor of a library. There are also other reasons to use exceptions. + They free the user from needing to clutter up code with lots of return code checking. This makes + code easier to read and let's you focus more on the algorithm you are trying to implement and less + on the bookkeeping. + </p> + <p> + Finally, it is important to note that there is a place for return codes. When you answer "no" + to questions 1 and 2, I suggest using exceptions. However, if you answer "yes" to even one + of them then I would recommend pretty much anything other than throwing an exception. In this + case error codes are often an excellent idea. + </p> + + + <p> + As an aside, it is also important that your exception classes inherit from + <a href="other.html#error">dlib::error</a> to maintain consistency with the rest of the library. + </p> + </ul> + </li> + + + <!-- **************************** --> + <anchor>9</anchor> + <li> <h3>Write portable code</h3> + <ul> + <li> <b>Don't complicate the build process </b> + <ul> <p> + One of dlib's design goals is to not require any installation + process before it can be used. A user should be able to copy + the dlib folder into their project and have it just work. + </p> + <p> + In particular, using dlib in a project should not make it difficult to + compile the project from the command line. For example, all the + example programs provided with dlib can be compiled using a single + statement on the command line. + </p> + <p> + Similarly, the user should be able to check the dlib folder into whatever + version control system they use without running into any difficulties. + The user should then be able to check out copies of the code on any + of the dlib supported platforms and have their project build without + needing to mess with anything. + </p> + </ul></li> + <li> <b>Don't make assumptions about how objects are laid out in memory. </b> + <ul> <p> + If you have been following the prohibition against messing around with + pointers then this won't even be an issue for you. Moreover, just about the only + time this should even come up is when you are casting blocks of + memory into other types or dumping the contents of memory to an I/O channel. + All of these things are highly non-portable so don't do them. + </p> + <p> + If you want a portable way to write the state of an object to an + I/O channel then I recommend you use the <a href="other.html#serialize">serialization</a> + capability in dlib. If that doesn't suit your needs then do + something else, but whatever you do don't just dump the contents of memory. + Convert your data into some portable format and then output that. + </p> + <p> + As an example of something else you might do: suppose you have a bunch of integers + you want to write to disk. Assuming all your integers are positive numbers representable + using 32 or fewer bits you could store all your numbers in + <a href="other.html#uint32">dlib::uint32</a> variables and then convert them + into either big or little endian byte order and then write them to an output stream. + You could do this using code similar to the following: + + <code_box> +dlib::<a href="other.html#byte_orderer">byte_orderer</a> bo; +... +bo.host_to_big(my_uint); +my_out_stream.write((char*)&my_uint, sizeof(my_uint)); +... </code_box> + + <p> + There are three important things to understand about this process. First, you need + to pick variables that always have the same size on all platforms. This means you + can't use <i>any</i> of the built in C++ types like int, float, double, long, etc. All + of these types have different sizes depending on your platform and even compiler settings. + So you need to use something like dlib::uint32 to obtain a type of a known size. + </p> + <p> + Second, you need to convert each thing you write out into either big or little endian byte order. + The reason for this is, again, portability. If you don't explicitly convert to one + of these byte orders then you end up writing data out using whatever byte order + is used by your current machine. If you do this then only machines that have the same + byte order as yours will be able to read in your data. If you use the dlib::byte_orderer + object this is easy. It is very type safe. In fact, you should have a hard time even getting + it to compile if you use it wrong. + </p> + <p> + The third thing you should understand is that you need to write out each of your + variables one at a time. You can't write out an entire struct in a + single ostream.write() statement because the compiler is allowed to put any + kind of padding it feels like between the fields in a struct. + </p> + <p> + You may be aware that compilers usually provide #pragma directives that allow you + to explicitly control this padding. However, if you want to submit code to dlib + you will not use this feature. Not all compilers support it in the same way and, + more importantly, not all CPU architectures are even capable of running code that + has had the padding messed with. This is because it can result in the CPU attempting + to perform what is called an "unaligned load" which many CPUs (like the SPARC) are + incapable of doing. + </p> + <p> + So in summary, convert your data into a known type with a fixed size, then convert + into a specific byte order (like big endian), then write out each variable individually. + Or you could just use <a href="other.html#serialize">serialize</a> and not worry about all + this horrible stuff. :) + </p> + + </p> + </ul> + </li> + + <li> <b> All code that calls functions that aren't in dlib or the C++ + standard library must be isolated inside the API wrappers.</b> + <ul><p> + If you want to contribute code to dlib which needs to use something that isn't + in the C++ standard then we need to introduce a new library component + in the <a href="api.html">API wrappers</a> section. The new component would + provide whatever functionality you need. This new component would have + to provide at least POSIX and win32 implementations. + </p> + <p> + It is also worth pointing out that <i>simple</i> wrappers around operating system + specific calls are usually a bad solution. This is because there are + invariably subtle, if not huge, differences between what is available on different + operating systems. + So being truly portable takes a lot of work. It involves reading everything + you can find about all the APIs needed to implement the feature on each target platform. + In many cases there will be important details that are undocumented and you will + only be able to find out about them by searching the internet for other developers + complaining about bugs in API functions X, Y, and Z. All this stuff needs to be abstracted + away to put a portable and simple interface in front of it. So this is a task + that shouldn't be taken lightly. + </p> + </ul> + </li> + </ul></li> + + + <!-- **************************** --> + <anchor>10</anchor> + <li> <h3>Library components should have regression tests</h3> + <ul> + <p> + dlib has a <a href="other.html#dlib_testing_suite">regression test suite</a> located in + the dlib/test folder. Whenever possible, library components should have tests + associated with them. GUI components get a pass since it isn't very easy to setup + automatic tests for them but pretty much everything else should have some sort + of test. + </p> + </ul> + </li> + + <!-- **************************** --> + <anchor>11</anchor> + <li> <h3>You must use the Boost Software License</h3> + <ul> + <p> + Having the library use more than one open source license is confusing + so I ask that any code contributions be licensed under the Boost Software + License. + </p> + </ul> + </li> + + + </ul> + + + <!-- **************************** --> + + + + + + </body> + + + + <!-- ************************************************************************* --> + +</doc> + |