We've likened it to having someone review a paper you've written: you often read what you think you wrote, not what's actually written.
This got me to questioning what others have found to be transformative in their development practices.
1–10 of 215 posts
We've likened it to having someone review a paper you've written: you often read what you think you wrote, not what's actually written.
This got me to questioning what others have found to be transformative in their development practices.
When I'm able to greenfield something myself, and use this from day one, I tend to very naturally end up with the "well-separated monolith" that some people are starting to talk about. I have on multiple occasions had the experience where I realize I need to pull some fairly significant chunk of my project out so it can run on its own server for some reason, and it's been a less-than-one-day project each time on these projects. It's not because I'm uniquely awesome, it's because keeping everything testable means it has to be code where I've already clearly broken out what it needs to function, and how to have it function in isolation, so when it actually has to function in real isolation, it's very clear what needs to be done and how.
Of all the changes I've made to my coding practice over my 20+ years, I think that's the biggest one. It crosses languages. At times I've written my own unit test framework when I'm in some obscure place that doesn't already have one. It crosses environments. It crosses frontend, backend, command line, batch, and real-time pipeline processing. You need to practice writing testable code, and the best way to do it is to just start doing it on anything you greenfield.
My standard "start a new greenfield project" plan now is "create git repo, set up a 'hello world' executable, install test suite and add pre-commit hook to ensure it passes". Usually I add what static analysis may be available, too, and also put it into the pre-commit hook right away. If you do it as you go along, it's cheap, and more than pays for itself. If you try to retrofit it later.... yeowch.
SQL, Python, PHP, JavaScript, and many aspects of Unix and the C/Make toolchain all come to mind.
Mind you, I don't like all of the above. At least 2 in particular I definitely wouldn't mind seeing "just go away."
But I do recognize that they have special staying power. And they didn't get this power by accident.
REPL means Read-Eval-Print-Loop and its a place where you can run code immediately and get immediate feedback. For example F12 in your browser and use the console to do 1+1. But you can also use that console to interact with your code in the browser, the DOM and make http requests.
But I also see REPL as a principle - to get as quick feedback from the code you write as possible, and things that help this are:
* Quick compile times
* Unit tests
* Continuous integration
So that each stage is as quick as possible. I write code and within as second or two know if it failed a test. Within a few seconds maybe I can play with the product locally to test it manually. Once committed, I can see it in production or a staging environment at least pretty quickly.
You can then have bigger REPL loops where a product manager can see your initial code fairly quickly, give you feedback and you can get stated on that right away and get it out again for review quickly.
I don't think there is any excuse not to work like this given the explosion of tooling in the last 20 years to help.
2. YAGNI
Writing over elaborate code because it is fun! That's fun at first but you soon learn it's better to write what is needed now. There is a balance and writing absolutely shit code is not an excuse, but adding too generic code because of stuff that might happen is also a problem.
https://github.com/nikitavoloboev/dotfiles/blob/master/zsh/a...
Even for legacy projects, starting with adding regression tests for every bug you find is a great way to introduce testing. And when you add new features, you can write tests for that as well.
I find that a FP mindset is helpful mostly because it tends to reduce the amount of global or spread-around state. This in turn makes testing and quickly iterating in a REPL a lot easier. Also when later the time comes to debug, it's much simpler if you don't have a huge amount of state to set up first.
And even if a lot of state is required, having it be an explicit input to a procedure is helpful because it makes it much clearer what you need to set up when doing manual testing.
I would say: Automated testing and a functional programming mindset. Even for legacy projects, starting with adding regression tests for every bug you find is a great way to introduce testing. And when you add new features, you can write tests for that as well. I find that a FP mindset is helpful mostly because it tends to reduce the amount of global or spread-around state. This in turn makes testing and quickly iter…
By far, starting to write automated testing as I code. The sheer number of bugs I find immediately and the number of bugs I find from changes that I didn't expect would be enough to justify it, but what is even better is that it forces me to keep my code testable , which also happens to correspond fairly closely to well-architected code . Not perfectly, but for something that is automated and always running, it's rea…
At the team level, probably CI/CD. It forces us to break the monolith into digestible chunks and makes regression testing easier.