Software Engineering Tips
- Programming is more about reading than writing. Write clear nice code.
It’s harder to read code than to write it.
—Joel Spolsky (Things you should never do)
- If your boss wants you to learn/try something new, go for it. They are literally paying you to learn something and this is a no-brainer!
- Good knowledge of some technology (library, language, framework) consists also of knowing to effectively work with its documentation online.
- It’s possible that a code is complex and you are interpreting the pain of understanding that complexity as a code quality problem.
- Understanding codebase includes knowing its history and past decisions.
- Use version control. Use git.
- Put everything that has been created manually in version control.
- Some tips on git in terminal
- Automate whatever you can.
- Make your work reproducible, use Makefiles.
- Check spelling in comments. It improves grepping your code.
- Use automatic formatting and linting
- black, flake8 for Python
- Keep lines short (up to 80 chars).
- Do pair-programming.
- Write down your learnt wisdoms (like this very page).
- keep the code that changes together close together
- Do not factor your code too early
- Write code in the highest-level language possible.
- Scientists writing software need to write code that both executes correctly and can be easily read and understood by other programmers (especially the author’s future self).
- Dependency is worse than redundancy arguments
- Do not use frameworks; Just don’t!
- Prefer standard library over third-party libraries. You should also read the documentation of the std. library.
- Avoid excesive nesting, see this nice explanation. Use up to 3 indentation levels for better readibility.
- Never fix a bug and refactor in the same pull request.
- Review your code with git diff before commit. Review it in PR, in a different environment, with fresh eyes.
- Write deep functions/modules (a simple API, complex code).
- DRY: don’t repeat yourself
- Define variables close to their point of use.
- Don’t waste vertical space.
- Considef inlining variables that are used only once.
- Inline functions that are used only once.
One of my most productive days was throwing away 1,000 lines of code.
–Ken Thompson (apparently)
- great code doesn’t need comments but
- explain reasoning behing a hard-to-read code or
- explain the state not to reinvent wheel (or refactor again just to learn that you did it already and found out it’s a bad idea at the end)
- Comments in the code review tool are not helpful for future code readers.
- Turn bugs into test cases.
- Write test for a bug before fixing it.
- Test against Reality.
- Test-driven development is probably an overkill.
Setup / hardware
- Minimize your requirements, it’s more robust.
- It’s easy to work on 2 monitors but hard when you are on your laptop.
- Adding more screens won’t help you much, learning how to effectively use limited resources will.
- Use some simple and efficient window manager (if you can). I use awesome wm.
Strive for loosely coupled architecture
How to know if our architecture is loosely coupled. One of the simplest ways is ensuring that it’s easy to replace or delete parts of your application. If it’s hard to remove parts of your application, your application is tightly coupled. Source
- Tips for stable and portable software
- My guiding principles after 20 years of programming – 20 guiding principles learnt over 20 years of Alex Ewerlöf
python -m timeit -s "setup code" "benchmark code"
- there are a few more libraries:
- A nice overview
- The standard library contains two implementations: profile and cProfile
Plaintext / markdown
- Use semantic linefeed.
- Use markdown wherever possible.
- Use git if possible and commit often (or better automatically).
- Read The Plain Person’s Guide to Plain Science.
- Never use black
- There are only a few basic rules to a good design
- Beware frameworks: 1
- Minimalism in UI
- Get inspired with a beautiful typography, look at Tufte
- Better spacing
- Dead simple CSS rules
- Do you really need those 1500 npm packages to add a tooltip which will work in all 150 browsers?
- BEM naming
- Try not to use non-standard fonts.
- Do not hotlink media it’s impolite and unstable.
- Use WEBP for pictures (photos) instead of the surpassed PNG, JPEG, …
- Generate sites with static site generators, e.g. Hugo used for this very page.
- Everything what behaves as a link should be HTML link (accessibility).
- Design webpages to last.
- Use permalinks because Cool URIs don’t change.
- Monochromatic icons
- Check your (inter-)links regularly, e.g. with linkcheck
- Minimize the number of pages, do not paginate. Make long (lightweight) pages.
- All page-change-actions should have their own URLs (router).
- Do not use CDNs as they might track your users.
GNU make manual
Do not use program-specific color schemes, use your terminal’s schemes.
Scripting, Bash, shell
- write scripts for whatever you can to automate/simplify things
- use cronjob, systemd timers,
.bashrc, aliases, Bash functions, …
- use cronjob, systemd timers,
- Write idempotent scripts.
- Use plain text formats to exchange simple data.
- use JSON for structured data if necessary, avoid yaml, kill XML with fire
- grangipanni: turn prefixed strings into tree structure
- gron: flatten JSON to a greppable text
- pup: process HTML with CSS selectors
- There is no perfect language. Each has its own (dis-)advantages.
- Learn more than one language.
- Learn more paradigms (functional, imperative) to be able to choose what is the most suitable for a task.
- Python is great for prototyping.
- Use formatting (black) and type checkers (mypy).
- Read stdlib documentation to avoid unnecessary use of libraries.
- Profile your code to make if faster
- Comparison of type systems article
- Best practices
- Advanced Python Resources – a discussion on HN
Text editors, IDEs
- Differentiate between an IDE and a text editor: the former is Unix, the latter Vi.
- It’s useful to learn something ubiquitous (vi, ed, ex, nano).
- How to grok at vim a legendary StackOverflow answer
- Seven habits of effective text editing – Bram’s tips
- Vim cheatsheet
- Vim bindings everywhere – apps where you can use Vim keybindings
- Light color scheme
- At least one Vim trick you might not know – a few nice tricks
- kanata advanced customization of keyboard
System Design, DevOps
- Monitoring is a pain – tips for maintaining monitoring systems
- Monitoring tips:
- define a hard limit for retention for metrics early on (30 days is a good default)
- use Thanos or Cortex if metrics are the primary observability tool, SaaS solutions are very expensive
- What we talk about when we talk about System Design – late-bind on design, talk about the problem, not existing systems… several good tips on how to design systems
Various and general
Pary’s notes on the art of programming
Pavel Rychlý is a former colleague (and kinda boss) of mine. I liked his approach to programming which he was teaching to us. Here I enclose some of his wisdom (taken from his slides with permission).
What is a good program/system
- what are the features of a good program
- does exist something like that?
- how can we create such thing?
Features of a good program
- easy to use
- easy to read
- without errors
Features of a good program how it is taught at Computer Science schools (but we have different priorities)
- without errors – correct
- covers all cases – complete
- sometimes proof exists/wanted
- as a bonus
- not taught
MIT approach (The Right Thing, !! we do NOT want this !!)
Correctness the design must be correct in all observable aspects. Incorrectness is simply not allowed. Consistency the design must be consistent. A design is allowed to be slightly less simple and less complete to avoid inconsistency. Consistency is as important as correctness. Completeness the design must cover as many important situations as is practical. All reasonably expected cases must be covered. Simplicity is not allowed to overly reduce completeness. Simplicity the design must be simple, both in implementation and interface. It is more important for the interface to be simple than the implementation.
“The Right Thing” programmers write bad programs
emphasis on correctness and completeness complicates everything programs are complicated and full of errors complicated means hard to maintain don’t follow that way
New Jersey approach (Unix) (this is our way)
Simplicity the design must be simple, both in implementation and interface. It is more important for the implementation to be simple than the interface. Simplicity is the most important consideration in a design. Correctness the design must be correct in all observable aspects. It is slightly better to be simple than correct. Consistency the design must not be overly inconsistent. Consistency can be sacrificed for simplicity in some cases, but it is better to drop those parts of the design that deal with less common circumstances than to introduce either implementational complexity or inconsistency. Completeness the design must cover as many important situations as is practical. All reasonably expected cases should be covered. Completeness can be sacrificed in favor of any other quality. In fact, completeness must be sacrificed whenever implementation simplicity is jeopardized. Consistency can be sacrificed to achieve completeness if simplicity is retained; especially worthless is consistency of interface.
- Keep it simple, stupid
- keep it short and simple
Simplicity should be a key goal in design and unnecessary complexity should be avoided
You aren’t gonna need it
Always implement things when you actually need them, never when you just foresee that you need them.
- never handle something without an example
- never handle something without a real example
- don’t generalize – handle only cases that have already occurred
How to achieve Simplicity
- small number of lines
- divide code into small (independent) modules
- small (zero) number of dependencies
- small number of methods
- small number of parameters
- use frameworks
- multiple inheritance
- more than three levels of nesting
- easy to read
- easy to understand
Simplicity is not easy
E = mc² is easy to understand but it was hard to discover.
no fast hacks
sometimes you have to try several ways to find the simple one
- A nice write-up with tricks
- Zen of Python, PEP 20 (
python -c 'import this')
- Software 2.0 (Andrej Karpathy)
- Programmer Competency Matrix
- Teach Yourself Programming in Ten Years
- You might not need an effect – React
- Generate music in Bash
- Terminal history and explanations.
- Few lesser known tricks, quirks and features of C
- Email explained from first principles
- Brown and green languages