Skip to content

Commit

Permalink
Merge pull request #22 from trbelleza/improve-docs
Browse files Browse the repository at this point in the history
Doc Improvements - Fixed Typos and Added Sample Snippets
  • Loading branch information
countable authored Sep 7, 2024
2 parents 36ca392 + 517df69 commit bf592f1
Show file tree
Hide file tree
Showing 14 changed files with 60 additions and 43 deletions.
16 changes: 7 additions & 9 deletions developers/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ The architecture should create a domain language and API that lets you do common

## Architecture Models

Here are some bodies of literature for thinking about architecture of interest. Many of these are focused in the Java world, since that ecosystem is very mature (preceeded more modern languages).
Here are some bodies of literature for thinking about architecture of interest. Many of these are focused in the Java world, since that ecosystem is very mature (preceded more modern languages).

Java also both has more cultural awareness of software architecture, and the language itself imposes more weight on developers than more modern languages,
which necessitates considering macrostructure and strategy earlier than (say) you can get away with using Python.
Expand All @@ -58,14 +58,12 @@ which necessitates considering macrostructure and strategy earlier than (say) yo

### Dependencies

1. **See any dependency as a cost**. The marginal benefit (so, minus opportunity cost of using no dependency) must be positive, ideally large.
2. When adding a new dependency, try to use one we've used in another project before.
3. Failing that, choose a popular dependency with lots of github stars and test coverage.
4. When adding a new dependency, share it in the \#developers slack channel (or ask another dev on your team directly) to see if anyone knows of a better option. Indicate what you need the dependency for.
4. Avoid dependencies that themselves depend on other optional dependencies where possible.
- ie) django-celery-tags depends on django AND celery which increases the risk of support blackout periods for new versions of Django and Celery.
5. If you must use a dependency, in general you should use the one that does the least additional things you're not going to use.
- Prefer micro-libraries which provide a small number of tools to accomplish a lot in your application's domain.
1. **See any dependency as a cost**. The marginal benefit (so, minus opportunity cost of using no dependency) must be positive, ideally large.
2. When adding a new dependency, try to use one we've used in another project before.
3. Failing that, choose a popular dependency with lots of GitHub stars and test coverage.
4. When adding a new dependency, share it in the \#developers Slack channel (or ask another dev on your team directly) to see if anyone knows of a better option. Indicate what you need the dependency for.
5. Avoid dependencies that themselves depend on other optional dependencies where possible - ie) django-celery-tags depends on django AND celery which increases the risk of support blackout periods for new versions of Django and Celery.
6. If you must use a dependency, in general you should use the one that does the least additional things you're not going to use. Prefer micro-libraries which provide a small number of tools to accomplish a lot in your application's domain.

### Data Model

Expand Down
35 changes: 27 additions & 8 deletions developers/CODING_STANDARDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Encourage consistent and effective coding practices in the team, arising out of

Covers principles of our coding standards, then branches out to specific language pages.

[Philosophy of Sofware Design](https://www.amazon.com/Philosophy-Software-Design-John-Ousterhout/dp/1732102201) is highly recommended reading. It's the book which will make you a better programming in the ways that matter most.
[Philosophy of Software Design](https://www.amazon.com/Philosophy-Software-Design-John-Ousterhout/dp/1732102201) is highly recommended reading. It's the book which will make you a better programming in the ways that matter most.

## Basics

Expand All @@ -27,39 +27,46 @@ These things should go without saying, but we'll say them here just in case :)
- Spend AT LEAST 10% of your time on writing tests and refactoring to reduce complexity.
- Every module, file, function, class and other component should have a clear "job" or clear set of related jobs. Someone who does not know the codebase should be able to deduce what a function is responsible fo.
- Follow conventions. For projects that do not currently follow our standards (open source, or new projects shared with other dev teams) but follows a different one, stick with that project's conventions unless we make a conscious decision to refactor the whole thing. Don't mix conventions.
- Make life easier for your team mates and future self by being consistent and thoughtful of what someone unfamiliar would think. The goal is your code should be obvious and easy to understand for a new programmer. Stick to conventions, and use comments to explain the story of your code, and why things are done a particular way.
- Make life easier for your teammates and future self by being consistent and thoughtful of what someone unfamiliar would think. The goal is your code should be obvious and easy to understand for a new programmer. Stick to conventions, and use comments to explain the story of your code, and why things are done a particular way.
- Humans should not spend time thinking about whitespace formatting. We use auto-formatters in place of coding standards in every case possible.

## Literature

We are observe teh following literature.
We are observe the following literature.

- [Domain Driven Design](https://en.wikipedia.org/wiki/Domain-driven_design) - We use Domain Modelling in our work
- [12 factor App Methodology](https://12factor.net/) - We use Container based deployments
- [Trunk based development](https://trunkbaseddevelopment.com/) - We use Trunk Based development
- [Agile Manifesto](https://agilemanifesto.org/) - We use Scrum
- [Clean Code](https://www.oreilly.com/library/view/clean-code/9780136083238/) - We write readable code
- [A Philisophy of Software Design](https://www.amazon.ca/Philosophy-Software-Design-John-Ousterhout/dp/1732102201) - We build for the long term
- [A Philosophy of Software Design](https://www.amazon.ca/Philosophy-Software-Design-John-Ousterhout/dp/1732102201) - We build for the long term

## Names

This section refers to the names of variables, database columns, classes, and any other case where a name is chosen in code.

Variables should hint what their data types are: in one glimpse I should be able to tell if a variable is e.g. a Boolean, string, etc.

**Example:**
```python
is_active = True # Boolean
user_name = "Alice" # String
item_count = 5 # Integer
```

Consider the book [Clean Code](https://www.oreilly.com/library/view/clean-code/9780136083238/) on
this topic and on writing short functions.

- Names should indicate *what* a function does in *business domain language* (see "Ubiquitous Language" in Domain Driven Design).
- Name length should be proportional to the variable's scope size. `x` is ok in a one liner, but not a global.
- Name length should be proportional to the variable's scope size. `x` is ok in a one-liner, but not a global.
- When an industry jargon (domain language) term is available, use that.
- ClassNames - Classes should use an upper camel case string of nouns.
- CONSTANT\_NAMES - Constants should be uppercase with underscores.

## Files

- Filenames should be lowercase with dashes (NOT SPACES) to separate words *except* for Python, which uses underscores in place of dashes.
- The purpose, and contents of any file should be as obvious as possible by its filename and location. **Throw in an example**
- The purpose and contents of any file should be as obvious as possible by its filename and location. **Throw in an example**
- Avoid repeated or unnecessary code, except where doing so is much more clear. Keep in mind less code is actually easier to understand, all other things being equal. So, it bears repeating, use the minimum amount of code in declarative domain language. Using the wrong abstraction can be worse than repeated code.
- Consider organizing by [colocation](https://povio.com/blog/maintainability-with-colocation/)

Expand All @@ -70,6 +77,18 @@ this topic and on writing short functions.
- Use pure functions where practical, and avoid side effects and global state.
- Modules should be responsible for a specific task or set of RELATED tasks.
- Modules should communicate through easily testable interfaces. A huge hierarchy of objects shouldn't be required to test a single method, because the method should only take arguments it actually uses (not a big tree which happens to contain those)
**Example:**
```text
# Bad: Complex dependency
def process_order(order: Order):
user = order.get_user()
payment = user.get_payment_method()
# ... do something with payment
# Good: Simplified dependency
def process_order(user: User, payment_method: PaymentMethod):
# ... process the order
```
## Error Handling
Expand All @@ -79,7 +98,7 @@ this topic and on writing short functions.
- When our system behaves incorrect, there should be a "500" error (often a stack trace), and it should be sent to a high urgency tracker like Sentry. These errors are a system design flaw that should always be fixed by us permanently. We should never 'expect' anything to appear in Sentry. We should be willing to bet it will always be empty.
- By contrast, when external systems fail (users enter something invalid, an external API rejects data, etc), these failures should result in a "400" error. They often will not require a code change by us, and should not be tracked in Sentry. They can generally be tracked in our application logs at the WARNING or ERROR level, and where possible, give feedback directly to the failed system (ie, tell the user their data is invalid).
- By contrast, when external systems fail (users enter something invalid, an external API rejects data, etc.), these failures should result in a "400" error. They often will not require a code change by us, and should not be tracked in Sentry. They can generally be tracked in our application logs at the WARNING or ERROR level, and where possible, give feedback directly to the failed system (ie, tell the user their data is invalid).
- When we are in an invalid state, it's better to throw an exception and avoid corrupting data or causing more confusing downstream issues. Catch errors early and loudly.
Expand All @@ -90,7 +109,7 @@ this topic and on writing short functions.
- Do not comment what is obvious from the code. "\# Increment the variable." is not a good comment.
- Do Document the rationale "why", the reason behind an implementation choice.
- Use TODO comments to indicate your intent for future work.
- Comment beside anything that's unintutive or unexpected to another reader.
- Comment beside anything that's unintuitive or unexpected to another reader.
- Do not leave actual code commented out unless you have a good reason. If you do have one, document that reason as a comment as well.
- See [this excellent guide from Stack Overflow's team](https://stackoverflow.blog/2021/07/05/best-practices-for-writing-code-comments/).
Expand Down
8 changes: 4 additions & 4 deletions developers/DEPENDENCIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This page covers dependency and framework selection and management. See also [he

**Scope**

Currently the page gives overall guidance on picking dependencies, and provides more specific deep guidance on Javascript frameworks in particular.
Currently, the page gives overall guidance on picking dependencies, and provides more specific deep guidance on Javascript frameworks in particular.

## How to Pick Dependencies

Expand All @@ -30,18 +30,18 @@ Javascript frameworks are a big discussion and there isn't a nice answer IMO.

The problem is our projects often live for 5 to 10 years. *Javascript frameworks do not.*

The problem of using the "framework of the day" is that Javascript frameworks only grow for about 3 years and then they always slowly die.
The problem of using the "framework of the day" is that Javascript frameworks only grow for about 3 years, and then they always slowly die.

jQuery is slowly fading away now, Angular has peaked and is losing market share to React.

React is close to peaking and is starting to lose
to Vue. By next year, Vue will be more popular than either Angular and React and it's a better framework so the answer is to use Vue, right?
to Vue. By next year, Vue will be more popular than either Angular and React, and it's a better framework so the answer is to use Vue, right?

The problem is, we build 5 apps in Vue, and then something else replaces it in 2 to 3 years, and we now have to support old apps in so many frameworks with dying communities. here are Pros and Cons of the major
frameworks we consider:

- jQuery is kind of unique since it's really a DOM library and not a framework. It's largely unnecessary now except as a plugin dependency and for animations. Otherwise, document.querySelector has replaced it (along with other modern dom methods, and fetch()). jQuery is also quite unprescriptive and so relatively harmless as a dependency compared to other libraries.
- Angular is currently a bit of a mess because it's split into 2 communities, Angular and AngularJS which are diverging frameworks.It also prescribes a lot of things like how to do Ajax, for no reason. However, we have it in several projects and it does the 2 way dom binding well making complex UI interactions simple.
- Angular is currently a bit of a mess because it's split into 2 communities, Angular and AngularJS which are diverging frameworks.It also prescribes a lot of things like how to do Ajax, for no reason. However, we have it in several projects, and it does the 2 way dom binding well making complex UI interactions simple.
- React is nicely scoped to just a single purpose, the view. And it's not split up like Angular is into 2 communities. However, while it doesn't over-prescribe in your application architecture, it does want you to use Webpack and require based architecture, which is awkward to work into existing projects. This (like angular) makes it tend towards an all or nothing approach. We also don't currently use React so it seems better not to throw it on the pile. Preact seems strictly better since it's identical but faster, with less plugin support.
- Vue suffers none of the above issues and is an easy to learn, succinct 2 way binding lib. But, do we want to start using yet another lib that does the same thing?
- Riot is like Vue or React, but simpler and less popular. Riot works well with Django because it has a powerful interoperability mechanism (observer pattern), and doesn't really prescribe much of anything so it's easy to add in at any time. However, Riot also has some fragmentation in its community, as v4 was a complete rewrite and introduced breaking changes from v3. Our projects still use Riot v3.
Expand Down
14 changes: 7 additions & 7 deletions developers/GIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ Countable uses [git flow](https://jeffkreeftmeijer.com/git-flow/) for branch nam

![image](/assets/images/git-flow.png)

1. `develop` is the main branch developers work on and test.
2. `master` is the "staging" branch, where the upcoming release is deployed weekly for testing and previews among the team.
3. `release` is the stable branch released to production. (most projects do not use release branches, we just continuously deploy `master`)
3. `feature/my-feature-name` feature branches contain your work for up to one day, before being merged back into `develop`.
4. `hotfix/my-bug-name` hotfix branches are merged into `master` to fix urgent problems in production.
1. `develop` is the main branch developers work on and test.
2. `master` is the "staging" branch, where the upcoming release is deployed weekly for testing and previews among the team.
3. `release` is the stable branch released to production. (most projects do not use release branches, we just continuously deploy `master`)
4. `feature/my-feature-name` feature branches contain your work for up to one day, before being merged back into `develop`.
5. `hotfix/my-bug-name` hotfix branches are merged into `master` to fix urgent problems in production.

Our feature branches are owned by a single person and very short-lived, see [trunk based development](https://paulhammant.com/2013/04/05/what-is-trunk-based-development/).

Expand Down Expand Up @@ -56,7 +56,7 @@ From the latter:

(Git will print out a link in the terminal that you may open to quickly create a pull request.)

3. Test that your changes dont't break anything.
3. Test that your changes don't break anything.

Run automated tests and check things you know other team members are
actively working on still work.
Expand Down Expand Up @@ -114,7 +114,7 @@ When you create your pull request:

- Remember to run Linting if applicable.
- It’s best to check the tests pass before merging (but you’ll be notified if they fail in Slack anyway). Don’t break the tests in `develop` for long… If you do, fix them ASAP because other devs will be unable to test their work otherwise.-
- Review it on BitBucket yourself because it lets you find embarassing
- Review it on BitBucket yourself because it lets you find embarrassing
mistakes without your team seeing them ;)
- Comment on specific lines you want the reviewer to notice.
- Check the checkbox option to automatically delete the branch after
Expand Down
2 changes: 1 addition & 1 deletion developers/HTML_CSS.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Use the [Prettier autoformatter and standard](https://github.com/prettier/pretti
- Try to write classes to be modular and reusable. This means that classes should reflect their function (e.g. `.success-message`) rather than the page element (`.my-feature-message`) if possible.
- Separate globally applicable CSS by typography, colors, layout and reset.
- Break CSS up by component. Some frameworks encourage or endorse this, but it's a good practice for all projects.
- Don't use capital letters or underscores for selector (class, id) names. Use dashes and lowerase.
- Don't use capital letters or underscores for selector (class, id) names. Use dashes and lowercase.
- Avoid inline styling, use classes instead.

```
Expand Down
4 changes: 2 additions & 2 deletions developers/INFOSEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ To define the base level information security policies at Countable and identify

**Scope**

Currently a stub; will first include baseline principles to keep in mind, then a more formal set of processes and checklists.
Currently, a stub; will first include baseline principles to keep in mind, then a more formal set of processes and checklists.

TODO
{: .label .label-yellow }
Expand All @@ -26,7 +26,7 @@ move actual policies we defined into here from Docs
* With regard to sensitive information, observe the principle of least privilege. This means provide as little access as possible, but enough as necessary to get work done.
* Avoid storing sensitive information on disk. Keep it in cloud based accounts.
* For laptops - please encrypt your disk if you have sensitiive information or access credentials for sensitive information stored there. DevOps staff must have encrypted disks with passphrase (entropy as above)
* Working from WiFi outside your home network? Use a VPN.
* Working from Wi-Fi outside your home network? Use a VPN.

## See Also

Expand Down
Loading

0 comments on commit bf592f1

Please sign in to comment.