Repository: scikit-learn/scikit-learn
Pull request: [MRG] Added tips for reading the code base
<!--
Thanks for contributing a pull request! Please ensure you have taken a look at
the contribution guidelines: https://github.com/scikit-learn/scikit-learn/blob/master/CONTRIBUTING.md#pull-request-checklist
-->

#### Reference Issues/PRs
<!--
Example: Fixes #1234. See also #3456.
Please use keywords (e.g., Fixes) to create link to the issues or pull requests
you resolved, so that they will automatically be closed when your pull request
is merged. See https://github.com/blog/1506-closing-issues-via-pull-requests
-->
Closes #12869 

#### What does this implement/fix? Explain your changes.

This PR adds a section in `contributing.rst` with tips to be more efficient at reading/understanding the code

#### Any other comments?

Feel free to add / change anything you deem relevant


<!--
Please be aware that we are a loose team of volunteers so patience is
necessary; assistance handling other issues is very welcome. We value
all user contributions, no matter how minor they are. If we are slow to
review, either the pull request needs some benchmarking, tinkering,
convincing, etc. or more likely the reviewers are simply busy. In either
case, we ask for your understanding during the review process.
For more information, see our FAQ on this topic:
http://scikit-learn.org/dev/faq.html#why-is-my-pull-request-not-getting-any-attention.

Thanks for contributing!
-->


Problem statement:
Creation of a 'Reading scikit-learn code' section in the docs?
Would you welcome a new subsection in (e.g.) the contributing guide, giving pointers on how to actually read and digest the existing code base? This could be a mix between general and sklearn-specific tips.

Lots of things may seem obvious for experienced programmers and contributors, but less experienced people might find the code base quite overwhelming at first. For example even simple utilities like `scale()` take more than 50 lines, while the bulk of the work could fit in a one-liner. It's easy to get lost in the details.

I was thinking of something like this (very roughly):

- It takes time and experience to efficiently read code. It's normal if it seems hard, because it is.
- Get acquainted with the estimator API: `fit`, `predict`, `fit_predict`...
- Identify the important parts and ignore the rest. In particular: **a lot** of the code (especially at the beginning of the `fit()` methods) is just doing input checking. Focusing on this part isn't worth it if you only need to understand what an algorithm is doing. Make sure you can identify those parts from the actual ML algorithm.
- Before trying to read a function / class, briefly read the parameters docstrings to have at least a vague idea of what each one of them is used for. Same for the attributes.
- Explain the `check_blahblah()` functions, e.g. `check_random_state()` or `check_cv`: take whatever as input but return an object with predefined type.
- We use cython to make things fast (.pyx and pxd files). Those files usually contain low-level routines that can probably be ignored during the first "reading sessions".
- ...

Any suggestion welcome.

Hints from issue discussion:
I personally like these kinda docs. Makes people less scared of reading code.
We could put it under https://scikit-learn.org/stable/developers/tips.html

> Any suggestion welcome.

"Use `git grep` to see where a particular function / estimator is used in a code base"
+1, we can make use of the glossary.

> We could put it under https://scikit-learn.org/stable/developers/tips.html

Personally I'd prefer https://scikit-learn.org/stable/developers/contributing.html since https://scikit-learn.org/stable/developers/tips.html is mostly for maintainers.


+1 for adding this, +1 for adding "git grep" (or VSCode search now) to find stuff, not only estimators but also functions.

Commit message: Added bullet point about inheritance

Patch to review:
diff --git a/doc/developers/contributing.rst b/doc/developers/contributing.rst
index a1a6068d53623..d4ab9c66deb0f 100644
--- a/doc/developers/contributing.rst
+++ b/doc/developers/contributing.rst
@@ -1395,3 +1395,62 @@ that implement common linear model patterns.
 
 The :mod:`sklearn.utils.multiclass` module contains useful functions
 for working with multiclass and multilabel problems.
+
+Reading the existing code base
+==============================
+
+Reading and digesting an existing code base is always a difficult exercise that
+takes time and experience to master. Even though we try to write simple code in
+scikit-learn, understanding the code can seem overwhelming at first, given the
+sheer size of the project. Here is a list of tips that may help make this task
+easier and faster (in no particular order).
+
+- Get acquainted with the :ref:`api_overview`: understand what :term:`fit`,
+  :term:`predict`, :term:`transform`, etc. are used for.
+- Before diving into reading the code of a function / class, go through the
+  docstrings first and try to get an idea of what each parameter / attribute
+  is doing. It may also help to stop a minute and think *how would I do this
+  myself if I had to?*.
+- The trickiest thing is often to identify which portions of the code are
+  relevant, and which are not. In scikit-learn **a lot** of input checking
+  is performed, especially at the beginning of the :term:`fit` methods.
+  Sometimes, only a very small portion of the code is doing the actual job. For
+  example looking at the ``fit()`` method of
+  :class:`sklearn.linear_model.LinearRegression`, what you're looking for
+  might just be the call the ``scipy.linalg.lstsq``, but it is buried into
+  multiple lines of input checking and the handling of different kinds of
+  parameters.
+- Due to the use of `Inheritance
+  <https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)>`_,
+  some methods may be implemented in parent classes. All estimators inherit
+  at least from ``BaseEstimator``, and from a ``Mixin`` class that enables
+  default behaviour depending on the nature of the estimator (classifier,
+  regressor, transformer, etc.).
+- Sometimes, reading the tests for a given function will give you an idea of
+  what is its intended purpose. You can use ``git grep`` (see below) to find
+  all the tests written for a function.
+- You'll often see code looking like this:
+  ``out = Parallel(...)(delayed(some_function)(param) for param in
+  some_iterable)``. This runs ``some_function`` in parallel using `Joblib
+  <https://joblib.readthedocs.io/>`_. ``out`` is then an iterable containing
+  the values returned by ``some_function`` for each call.
+- We use `Cython <https://cython.org/>`_ to write fast code. Cython code is
+  located in ``.pyx`` and ``.pxd`` files. Cython code has a more C-like
+  flavor: we use pointers, perform manual memory allocation, use OUT
+  variables (variables whose value is changed after a function call, which
+  is frowned upon in pure Python but extremely common in C), etc. Having
+  some minimal experience in C / C++ is pretty much mandatory here.
+- Master your tools.
+
+  - With such a big project, being efficient with your favorite editor or
+    IDE goes a long way towards digesting the code base. Being able to quickly
+    jump (or *peek*) to a function/class/attribute definition helps a lot.
+    So does being able to quickly see where a given name is used in a file.
+  - `git <https://git-scm.com/book/en>`_ also has some built-in killer
+    features. It is often useful to understand how a file changed over time,
+    using e.g. ``git blame`` (`manual
+    <https://git-scm.com/docs/git-blame>`_). This can also be done directly
+    on GitHub. ``git grep`` (`examples
+    <https://git-scm.com/docs/git-grep#_examples>`_) is also extremely
+    useful to see every occurrence of a pattern (e.g. a function call or a
+    variable) in the code base.


Code review comments:
diff_hunk: @@ -1395,3 +1395,62 @@ that implement common linear model patterns.
 
 The :mod:`sklearn.utils.multiclass` module contains useful functions
 for working with multiclass and multilabel problems.
+
+Reading the existing code base
+==============================
+
+Reading and digesting an existing code base is always a difficult exercise that
+takes time and experience to master. Even though we try to write simple code in
+scikit-learn, understanding the code can seem overwhelming at first, given the
+sheer size of the project. Here is a list of tips that may help make this task
+easier and faster (in no particular order).
+
+- Get acquainted with the :ref:`api_overview`: understand what :term:`fit`,
+  :term:`predict`, :term:`transform`, etc. are used for.
+- Before diving into reading the code of a function / class, go through the
+  docstrings first and try to get an idea of what each parameter / attribute
+  is doing. It may also help to stop a minute and think *how would I do this
+  myself if I had to?*.
+- The trickiest thing is often to identify which portions of the code are
+  relevant, and which are not. In scikit-learn **a lot** of input checking
+  is performed, especially at the beginning of the :term:`fit` methods.
+  Sometimes, only a very small portion of the code is doing the actual job. For
+  example looking at the ``fit()`` method of
+  :class:`sklearn.linear_model.LinearRegression`, what you're looking for
+  might just be the call the ``scipy.linalg.lstsq``, but it is buried into
+  multiple lines of input checking and the handling of different kinds of
+  parameters.
+- Due to the use of `Inheritance
+  <https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)>`_,
+  some methods may be implemented in parent classes. All estimators inherit
+  at least from ``BaseEstimator``, and from a ``Mixin`` class that enables
+  default behaviour depending on the nature of the estimator (classifier,
+  regressor, transformer, etc.).
+- Sometimes, reading the tests for a given function will give you an idea of
+  what is its intended purpose. You can use ``git grep`` (see below) to find
+  all the tests written for a function.
+- You'll often see code looking like this:
+  ``out = Parallel(...)(delayed(some_function)(param) for param in
+  some_iterable)``. This runs ``some_function`` in parallel using `Joblib
+  <https://joblib.readthedocs.io/>`_. ``out`` is then an iterable containing
+  the values returned by ``some_function`` for each call.
+- We use `Cython <https://cython.org/>`_ to write fast code. Cython code is
+  located in ``.pyx`` and ``.pxd`` files. Cython code has a more C-like
+  flavor: we use pointers, perform manual memory allocation, use OUT
+  variables (variables whose value is changed after a function call, which
+  is frowned upon in pure Python but extremely common in C), etc. Having
path: doc/developers/contributing.rst
text: @user1:
Maybe simplify this part. I don't think beginners need too much cython knowledge.