diff --git a/developers/ARCHITECTURE.md b/developers/ARCHITECTURE.md index 01450a187e..2daf66ea32 100644 --- a/developers/ARCHITECTURE.md +++ b/developers/ARCHITECTURE.md @@ -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. @@ -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 diff --git a/developers/CODING_STANDARDS.md b/developers/CODING_STANDARDS.md index e41b3e2cea..acd6d6bdec 100644 --- a/developers/CODING_STANDARDS.md +++ b/developers/CODING_STANDARDS.md @@ -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 @@ -27,19 +27,19 @@ 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 @@ -47,11 +47,18 @@ This section refers to the names of variables, database columns, classes, and an 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. @@ -59,7 +66,7 @@ this topic and on writing short functions. ## 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/) @@ -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 @@ -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. @@ -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/). diff --git a/developers/DEPENDENCIES.md b/developers/DEPENDENCIES.md index a8d13324cc..68cc0a7297 100644 --- a/developers/DEPENDENCIES.md +++ b/developers/DEPENDENCIES.md @@ -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 @@ -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. diff --git a/developers/GIT.md b/developers/GIT.md index 35b979b7a5..8f3993a475 100644 --- a/developers/GIT.md +++ b/developers/GIT.md @@ -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/). @@ -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. @@ -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 diff --git a/developers/HTML_CSS.md b/developers/HTML_CSS.md index bd610807a0..222065aa41 100644 --- a/developers/HTML_CSS.md +++ b/developers/HTML_CSS.md @@ -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. ``` diff --git a/developers/INFOSEC.md b/developers/INFOSEC.md index 10f3efdc3b..b73fff695b 100644 --- a/developers/INFOSEC.md +++ b/developers/INFOSEC.md @@ -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 } @@ -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 diff --git a/developers/JAVASCRIPT.md b/developers/JAVASCRIPT.md index 90c13db04c..844ecdf456 100644 --- a/developers/JAVASCRIPT.md +++ b/developers/JAVASCRIPT.md @@ -45,7 +45,7 @@ These are the most preferred libraries, but if the project is heavily invested i ## Performance -ie) We should use Fetch if possible because it saves 50KB. This may not sound like much but makes a big difference in the long run. Most web apps take 5 seconds to load on an average connection becasue of devs making many small decisions to add size to the bundle which hits our load time both in terms of bundle transfer but in JS parsing, and this leads to a mediocre experience. When a busy (and perhaps, highly paid) person is in a hurry, it's excruciating to wait a few extra seconds. This is made far worse for browser extensions which have to load IN ADDITION to the base website and all the other extensions so they especially need to be lean. What is the rationale for using Axios? (edited) +ie) We should use Fetch if possible because it saves 50KB. This may not sound like much but makes a big difference in the long run. Most web apps take 5 seconds to load on an average connection because of devs making many small decisions to add size to the bundle which hits our load time both in terms of bundle transfer but in JS parsing, and this leads to a mediocre experience. When a busy (and perhaps, highly paid) person is in a hurry, it's excruciating to wait a few extra seconds. This is made far worse for browser extensions which have to load IN ADDITION to the base website and all the other extensions so they especially need to be lean. What is the rationale for using Axios? (edited) # Vue and React @@ -57,7 +57,7 @@ ie) We should use Fetch if possible because it saves 50KB. This may not sound li # Error Handling Good error handling can save tremendous amounts of time for your team. - Display useful diagnostic info on failures in the console and on the screen. - - Make errors specific to the operation being performed. You can have nexted try/catch blocks as needed to attain this. + - Make errors specific to the operation being performed. You can have nested try/catch blocks as needed to attain this. - Consider that when your application fails, users will probably send you a screenshot. You want to make sure that screenshot contains the information to debug the issue. - Your error message to the user should explain how it affects them and what steps to take if possible. - Put context variables in your error string (no personal health info of course). `Failed to save user ID ${user.id}` diff --git a/developers/PROJECT_STANDARDS.md b/developers/PROJECT_STANDARDS.md index fed5e6e7a2..909ce7b820 100644 --- a/developers/PROJECT_STANDARDS.md +++ b/developers/PROJECT_STANDARDS.md @@ -74,7 +74,7 @@ DRAFT Front-end development is exciting, but also a challenge. This is due to the fact that there are so many tools available for so many different things, and this side of the world moves fast. Main considerations: -1. **Browser compability** - Does the website look good on Chrome? Firefox? Ipad? Galaxy? iPhone? +1. **Browser compatibility** - Does the website look good on Chrome? Firefox? Ipad? Galaxy? iPhone? 2. **Device compatibility** (Responsive Design) - On monitors that are not 1080p? 10 inch laptops at 1280 x 720? 3. **Automation** - Nowadays, you don't necessarily need to CODE for this, since there are tools like Babel, Normalize.css, Autoprefixer which help make this happen. @@ -88,7 +88,7 @@ On larger sites with an accessibility budget: Tooling for different areas can be in any of the following status: - - *Unspecified* - Use whatever you want as long as it's well supported. + - *Unspecified* - Use whatever you want as long as it's well-supported. - *Recommendation* - We recommend using a specific tool, but developer expertise or another reason could override this. - *Standard* - You should only deviate from this tooling choice for a specific reason. diff --git a/developers/PROTOTYPING.md b/developers/PROTOTYPING.md index af0d69f7b1..a8e6aa7ef1 100644 --- a/developers/PROTOTYPING.md +++ b/developers/PROTOTYPING.md @@ -29,9 +29,9 @@ This doesn't mean you should make a mess, it means you should keep it simple and ## Get A Prototype in Front of Real Users ASAP -1. *Get a prototype in front of real users ASAP*. +1. *Get a prototype in front of real users ASAP*. - All that matters is the absolutely most core functions work reasonably well and it's easy to understand. - - Therefore put effort into **clear design** and the **most basic feature set**. *Not* into *scalability*, *code quality*, or anything else. + - Therefore, put effort into **clear design** and the **most basic feature set**. *Not* into *scalability*, *code quality*, or anything else. 2. If you receive a positive market response, THEN refactor and clean up your code, add tests, and move to a larger user base, step 4. 3. If you need to pivot, you'll have no remorse or attachment to your crappy implementation. You're back to step 1, and can keep whatever parts are still useful. 4. Now, if your larger user base is engaged and growing, you can work on scalability and final architecture. diff --git a/developers/TESTING.md b/developers/TESTING.md index 7744409e40..9084206f35 100644 --- a/developers/TESTING.md +++ b/developers/TESTING.md @@ -26,7 +26,7 @@ Currently covers basic testing principles and bug reporting procedures. ## Bug Reporting Checklist -These are the required steps for reportings bugs at Countable. Make one Trello Card per bug. +These are the required steps for reporting bugs at Countable. Make one Trello Card per bug. *Your job when reporting a bug is to make it clear to the developer how to see the bug* diff --git a/developers/TRAINING.md b/developers/TRAINING.md index de07ae745f..4afc821faa 100644 --- a/developers/TRAINING.md +++ b/developers/TRAINING.md @@ -12,7 +12,7 @@ Lay the groundwork for continuous learning at Countable, demonstrating how to pu **Scope** -Currently covers "how to learn" and recommends dev-specific resources. +Currently, covers "how to learn" and recommends dev-specific resources. ## How To Learn diff --git a/developers/TRAINING_TOUCH.md b/developers/TRAINING_TOUCH.md index a1bb7bd473..4c0e10647f 100644 --- a/developers/TRAINING_TOUCH.md +++ b/developers/TRAINING_TOUCH.md @@ -8,7 +8,7 @@ nav_order: 13 # touch -Let’s learn how to make some files. A very simple way is to use the touch command. Touch allows you to the create new empty files. +Let’s learn how to make some files. A very simple way is to use the touch command. Touch allows you to create new empty files. ``` $ touch mysuperduperfile @@ -16,7 +16,7 @@ $ touch mysuperduperfile And boom, new file! -Touch is also used to change timestamps on existing files and directories. Give it a try, do an ls -l on a file and note the timestamp, then touch that file and it will update the timestamp. +Touch is also used to change timestamps on existing files and directories. Give it a try, do `ls -l` on a file and note the timestamp, then touch that file, and it will update the timestamp. There are many other ways to create files that involve other things like redirection and text editors, but we’ll get to that in the Text Manipulation course. diff --git a/developers/UX_FOR_DEVS.Md b/developers/UX_FOR_DEVS.Md index f81aeee69e..9190e67d0e 100644 --- a/developers/UX_FOR_DEVS.Md +++ b/developers/UX_FOR_DEVS.Md @@ -10,7 +10,7 @@ nav_order: 1 ## Use Systems * Use Flowbite, a Figma+CSS designs system, to help make the default design obvious and attractive. - * When developing a component, break them apart (decomopose) based on how they will be re-used. + * When developing a component, break them apart (decompose) based on how they will be re-used. * Always check if an component you're building already exists, or a similar one does you can re-use. ## Always auto-fill default values diff --git a/operations/PROJECT_MANAGEMENT/CRITICAL_PATH.md b/operations/PROJECT_MANAGEMENT/CRITICAL_PATH.md index 152b8dae43..86bc31a276 100644 --- a/operations/PROJECT_MANAGEMENT/CRITICAL_PATH.md +++ b/operations/PROJECT_MANAGEMENT/CRITICAL_PATH.md @@ -20,7 +20,7 @@ Identify dependencies to complete a finished product, and make sure the "critica The "critical path" is the *longest* list of dependencies to completing a project. To find this, work back from the goal. -For example, if the goal is to build a web applicaton, the critical path is something like this: +For example, if the goal is to build a web application, the critical path is something like this: - We want to build a web application. - To do that, we need to validate with users (usability test).