A collection of (mostly) technical things every software developer should know.
These are highly opinionated resources I recommend to every programmer regardless of their skill level or tech stack
When following the guidelines you should start with get Started and keep going in order to get the best bang for you buck. The following milestone chart can be used to get timeline focused results. Exp.
Milestone | Timeline | Action item |
---|---|---|
Getting familiar with OOP and functional Programing | 2 sprints | Research OOP and FP |
Identify blocks of code as OOP and FP | 2 sprints | Reviewing code and classify |
Practice writing code in your style | 2 sprint | Rewriting code to match your style |
Tabs or spaces? Curly brace on the same line or a new line? 80 character width or 120? Consistency matters. Readability matters. Arguing and stressing about one convention over another matters not. It is important to find a style that appeals to you. It can be OOP or Functional programing, find something you can defend when others judge your code.
- π Professor Frisby's Mostly Adequate Guide to Functional Programming
- π Practical Object Oriented Design in Ruby
Falsehood articles are a form of commentary on a particular subject, and are appreciated by the developer community at large for their effectiveness and terseness. They're a convenient written form to approach an unfamiliar domain by dispelling myths, point out common pitfalls, show inconsistencies and subtleties. Check the following Awesome list to go over common themes.
- Awesome Falsehoods π Curated list of falsehoods programmers believe in. Check for things you do not know about Strings, Addresses, Names, Numbers, Emails, Timezones and Dates and more.
- π₯ UC Berkeley, Data Structures Course
- Foundations of Data Structures - EDX
- Data Structures - Coursera
- Mathematics for Computer Science - Eric Lehman
- π Difficult Conversations
- π Crucial Conversations
- π How to Win Friends and Influence People
- π How to Count
- π Floating Point Guide
- π What Every Computer Scientist Should Know About Floating-Point Arithmetic
- π Basic Number Theory Every Programmer Should Know...
- π Unicode and Character Sets
- Homoglyphs
- Unicode Common Locale Data Repository
- π₯ ASCII
- π₯ UTF-8
- π Designing Data-Intensive Applications
- π Designs, Lessons and Advice from Building Large Distributed Systems
- π Time, Clocks and the Ordering of Events in a Distributed System
- π There is No Now
- π Jepsen: how different databases behave under partition
- π Fallacies of Distributed Computing Explained
- π Security Programming
- π Rolling Your Own Crypto
- π Cryptographic Right Answers
- π An Open Letter to Developers Everywhere (About Cryptography)
- π Foundations of Security: What Every Programmer Needs to Know
- OWASP Top 10
- Web Application Exploits and Defenses
- π Hashing, Encryption and Encoding
- π A Field Guide to Boxology
- π Out of the Tar Pit
- π No Silver Bullet β Essence and Accidents of Software Engineering
- π₯ Growing a Language
- π₯ CQRS and Event Sourcing
- π Practical Object Oriented Design in Ruby
- π₯ Evolutionary Software Architectures
- System Design: A Primer
- π How JavaScript works: part-1, 2, 3, 4
- π₯ Entity-Component-System Architecture with Unity by example
- π₯ Category Theory in Life
- π₯ Simple Made Easy
- π Speed In Software Development
- π₯ #NoEstimates
- π₯ The Myth of the Genius Programmer
- π₯ Making Badass Developers
- π The Ten Rules of a Zen Programmer
- π The mythical 10x programmer
- π The Debugging Mindset
- π₯ The Future of Programming
- π The Good Software Development Manifesto
- π₯ All the Little Things
- π Working Effectively with Legacy Code
- π Clean Code: A Handbook of Agile Software Craftsmanship
- π Test Driven Development: By Example
- β Going To Production Checklist
- π Release It!
- π Professor Frisby's Mostly Adequate Guide to Functional Programming
- π SICP: Structure and Interpretation of Computer Programs
- π Thirteen Ways of Looking at a Turtle
- π Programming Paradigms for Dummies: What Every Programmer Should Know
- Learn X in Y Minutes Learn the basics of a language in a highly condensed way.
- Hyperpolyglot Compare commonly used features of more or less similar languages side-by-side. Helps you to jump Python<->Ruby, Ocaml<->Haskell, etc.
- π Pomodoro for Programmers
- π Site Reliability Engineering
The Broken Windows Theory on Wikipedia
The Broken Windows Theory suggests that visible signs of crime (or lack of care of an environment) lead to further and more serious crimes (or further deterioration of the environment).
This theory has been applied to software development, suggesting that poor quality code (or Technical Debt) can lead to a perception that efforts to improve quality may be ignored or undervalued, thus leading to further poor quality code. This effect cascades leading to a great decrease in quality over time.
See also:
Adding human resources to a late software development project makes it later.
This law suggests that in many cases, attempting to accelerate the delivery of a project which is already late, by adding more people, will make the delivery even later. Brooks is clear that this is an over-simplification, however, the general reasoning is that given the ramp up time of new resources and the communication overheads, in the immediate short-term velocity decreases. Also, many tasks may not be divisible, i.e. easily distributed between more resources, meaning the potential velocity increase is also lower.
The common phrase in delivery "Nine women can't make a baby in one month" relates to Brooks' Law, in particular, the fact that some kinds of work are not divisible or parallelisable.
This is a central theme of the book 'The Mythical Man Month'.
See also:
Keep it simple and stupid. The most boring and most obvious solution is often the best. Although it sometimes takes months until you know which solution it is.
From the book "Site Reliability Engineering" (O'Reilly Media 2016) https://landing.google.com/sre/book/chapters/simplicity.html
Quote:
: The Virtue of Boring
Unlike just about everything else in life, "boring" is actually a
positive attribute when it comes to software! We donβt want our
programs to be spontaneous and interesting; we want them to stick to
the script and predictably accomplish their business goals.
Example: Pure Functions are great. They are stateless, their output can be cached for ever, they are easy to test.
But it is not only about code. It is about the experience of all stakeholders: Users, sales people, support hotline, developers, ....
It is hard work to keep it simple.
One think I love to do: "Increase the obviousness".
One tool to get there: Use a central wiki (without spaces), and define terms. Related text from me: Documentation in Intranets: My point of view
- Not existing code is the best: Less code, less bugs
- Code maintained by a reliable upstream (like Python, PostgreSQL, Django, Linux, Node.js, Typescript, ...) is more reliable than own code.
Things are much easier to implement and predict if you just have one method call. One request and one response. You don't have an open connection and a reference to a remote object which executes on a remote server.
Look at all the dated protocols which are like a human conversation between a client and a server: SMTP, IMAP, FTP, ... Nobody wants the client and the server to have a chatty dialog like this:
Client: My name is Bob
Server: Hi Bob, nice to meet you.
Server: But are you really Bob?
Server: Please prove to me that you're Bob. You can use method foo, bar, blu for authentication
Client: I choose method "blu"
Server: Ok, then please tell send the magic blu token
Client: Here it is xyuasdusd8.. I hope you like it.
Server: Fine, I accept this. Now I trust you. Now I know you are Bob
Client: Please show me the first message
Server: here it is:
Server: ....
Client: looks like spam. Please delete this message
Server: Now I know that you want to delete this message.
Server: But won't delete it now. Please send me EXPUNGE to execute the delete.
Client: grrrr, this is complicated. I already told you that I want the message to be deleted.
Client: EXPUNGE
...
Of course roughly the same needs to be done with http. But http you can cut the task into several smaller http requests. This gives the service the chance of delegating request-1 to server-a and request-2 to server-b. In the cloud environment containers get created and destroyed in seconds. It is easier without long living connection.
In above case (IMAP protocol) the EXPUNGE is like a COMMIT in relational databases.It is very handy to have a transactional database to implement a service. But it makes no sense to expose the transaction to the client.
Stateless is like IPO: Input-Processing-Output.
The shell is nice for interactive usage. But shell scripts are unreliable: Most scripts fail if filenames contain whitespaces. Shell-Gurus know how to work around this. But quoting can get really complicated. I use the shell for interactive stuff daily. But I stopped writing shell scripts.
Reasons:
- If a error happens in a shell script, the interpreter steps silently to the next line. Yes I know you can use "set -e". But you don't get a stacktrace. Without stacktrace you waste a lot of time to analyze why this error happened.
- AFAIK you can't do object oriented programming in a shell. I like inheritance.
- AFAIK you can't raise exceptions in shell scripts.
- Shell-Scripts tend to call a lot of subprocesses. Every call to grep, head, tail, cut creates a new process. This tends to get slow. I have seen shell scripts which start thousand processes per second. After re-writing them in Python they were 100 times faster und 100 times more readable.
- I do this "find ... | xargs" daily, but only while using the shell interactively. But what happends if a filename contains a newline character? Yes, I know "find ... -print0 | xargs -r0", but now "find.. | grep | xargs" does not work any more .... It is dirty and will never get clean.
- Look at all the pitfalls: Bash Pitfalls My conclusion: I prefer to walk on solid ground, I don't write shell scripts any more.
Even Crontab lines are dangerous. Look at this:
@weekly . ~/.bashrc && find $TMPDIR -mindepth 1 -maxdepth 1 -mtime +1 -print0 | xargs -r0 rm -rf
Do you spot the big risk?
Do the filtering in the database. In most cases it is faster then the loops in your programming language. And if the DB is not fast enough, then I guess there is just the matching index missing up to now.
Imagine you have three models (users, groups and permissions) as tables in a relational database system.
Most systems do the permission checking via source code. Example: if user.is_admin then return True
.
Sooner or later you need the list of items: Show all items which the current user may see.
Now you write SQL (or use your ORM) to create a queryset which returns all items which satisfy the needed conditions.
Now you have two implementations. The first if user.is_admin then return True
and one which uses set operations (SQL). This is redudant and looking for trouble. Sooner or later your permission checks get more complex and then one implementation will get out of sync.
That's why I think: do permission checking via SQL
ORM (Object-relational mapping) makes daily work much easier. Above heading is a stupid joke. Clever people use tools to make work simpler, more fun and more convenient. ORMs are great.
Some (usualy elderly) developers fear that a ORM is slower than hand-crafted and optimized SQL. Maybe there are corner cases where this prejudice is true. But that's not a reason to avoid ORMs. Just use them, and if you hit a corner case, then use raw SQL.
See premature optimization is the root of all evil
Make your live easy, use ORM.