Skip to content

BestPractices

peder2911 edited this page Aug 9, 2021 · 2 revisions

Practices

This article covers (best) practices followed by the ViEWS team. These practices should be followed in almost all cases when contributing to ViEWS 3. The purpose of outlining as set of best practices is to ensure long-term maintainability and stability for the codebase.

Language

The primary programming language used to write ViEWS 3 is Python, specifically Python 3.8. A deep and intimate knowledge of Python is necessary, although the ViEWS 3 codebase should be as simple and approachable as possible.

The service-oriented architecture of ViEWS 3 makes it possible to partially adopt other languages, such as for specialized or performance critical tasks. For now, Python is the only language applied.

Idioms

ViEWS 3 is written in a mostly functional style, with an emphasis on simple, testable, composable granular functions.

In the context of Python, one slightly exotic aspect of the ViEWS 3 code is the use of monads for error handling. For a good introduction to how monads make programming with error-prone functions safer, see this excellent blogpost. The monad implementation used is pymonad.

In some parts of ViEWS, language and framework (numpy) "exploits" and tricks are used whenever large performance gains can be achieved. These sections of the code might be more difficult to read, but are rigorously tested, and should not need much "maintenance" (example).

Testing

All non-trivial code should be tested. Libraries we use are assumed to be tested and stable, but all custom logic and operations should have associated unit tests.

Testing code that relies on external resources, which most services do, can be tricky, but is simple with the proper tooling. For mocking HTTP requests, use httpretty. For mocking SQL Alchemy sessions, use UnifiedAlchemyMagicMock from alchemy-mock.

Consistency

For each service, one should use one and only one tool in each domain. This means that if a service uses SQL Alchemy for its database operations, then you should write database code for that service using something else. In similar fashion, if a service uses unittest for its tests, then you need to write tests with unittest.