Share your thoughts!
- The project should start up with one click or one command. It's fine if I need to configure credentials or something similar, but beyond that, your project should be so easy to start that your mom could do it. If the project requires me to locally install a database, configure ports, or anything of the like, that's a shining red flag that things are very wrong.
- The underlying architecture and rationale should be documented and this document should be reasonably up to date. Whoever is the lead developer on the project should be responsible for this. Not all details need to be covered, but the main principles and the driving business requirements behind it need to be clearly stated and up to date. If there's no broad documentation, I consider the project to already be off the rails, not just heading that way.
- There should be a concept of testing. You don't need to have tests yet, especially if you're still prototyping, but you need to have a very clear idea of what you will test, how, and how you'll get there.
- Formatting isn't a discussion point. Whatever stylistic preferences there are are covered by linting and automatic formatting. If I clone the project, it should be reasonably hard for me to do things the wrong way and fairly easy to do them the right way.
- Branch management, code review, etc. All of this falls in the same pot for me, no one should have the ability to push directly to master, all changes need to go through review, pass lint, tests, etc before they can be merged. Doesn't matter if you're the lead dev or a summer intern.
You'll notice that all of the above are procedural issues, not code specific issues. I firmly believe that by nailing the underlying process first, you make it easy to build good software and hard to build bad software.
My experience is that technology has never stood in my way. It may be inconvenient, but I always find a way to work with it.
The thing that has always been in my way is other people. Always.
For me:
1. A boss who has a clue. Who has actually built software deployed to production at least once. Who understands the customer's business. Who manages things and leads people, not the other way around. Who gives me my assignments, the resources I'll need, and leaves me alone.
2. Project managers who know how to run projects.
3. Business analysts who know how to conduct analysis.
4. The decision to either go agile or not. No more sprints, stand-ups, scrum masters, product owners, retrospectives, etc, etc, etc, unless we do it completely and do it right.
5. Anyone, anywhere who writes something, anything down. No more, "Don't you remember when Sue asked Michael and he got Fred to tell us in that skype?" (My answer is always, "No.")
6. Any environment where I spend 90% of my time programming and 10% on overhead, not the other way around.
7. Authority to go along with my responsibility. I'm tired hitting every deadline and forced to wait weeks (or months!) for Peer Review, Code Review, Design Review, Standards Review, User Acceptance Testing, Integration Testing, Quality Review (against what standard?), Steering Committee approval, Leadership approval, approval from God herself...
8. A minimal acceptable competence level for my teammates, achieved by proper vetting (including tech interviews and tests). Software development is achieved as fast as the weakest link, not the strongest one.
9. No meetings!!! If it isn't written down, it isn't. If it is written down, you probably don't need to meet.
I could go one all day, but I'm late for a meeting. :-(
Syntax highlighting. Look up documentation at callsite. Jump to definition. Run a test from the editor. Debug executables from within the editor. Fuzzy find file by name (for instance, typing "pluginfancymixi" should turn up something at "project/Plugins/third_party/username/project_name/fancy_mixin.language"). Third-party plugin support. Ability to have per-repo configurations
* Searching code:
Should be faster than grepping a bunch of directories. Supports wildcard searching. Bonus: tooling support for finding identifiers, callsites, usages, etc
* Development environment:
Any executable or test can run in one step (zero if possible). If possible, should be able to run multiple instances of your app at once. For example, I should be able to leave a webserver running so that my code reviewer can test it without pulling the branch
* Team environment:
Small PRs. Quick reviews. Tuned balance between senior and junior engineers. Should have enough senior engineers that they don't feel overwhelmed by the mentorship+training part of their job.
Edited: formatting
I currently work on a project where infra is a complete mess, but another developer on my team takes care of everything, including setting up our own clandestine k8 cluster to work around the unreasonable limitations of the system we're supposed to be working on. I love him. The downside is that we're not compliant with all the rules we're supposed to comply with, but there's no way for us to comply and still do anything, so I'm happy we're doing stuff.
In an ideal situation, an infra team would take care of all of this for us and ensure it's easy for us to be compliant while still getting stuff done.
Beyond that, the ideal would be a unix-based shell, my preferred IDE (IntelliJ), the ability to install the dev tools I need, proper version control, clear, concise descriptions of what to implement, my own input on what and how to implement, and access to stakeholders/end-users.
* Node.js on backend, using a thin db layer (not an orm) like sequelize. My newer projects also use TypeScript on back end and share models with front end with a lerna setup
* React.js with TypeScript (default create-react-app setup) on frontend; multiple smaller apps for each business unit/functional area; some limited sharing of UI components between these apps (turns out not that much needs to be shared really)
* Everything in a mono repo and edited in VS.Code
* Deploy by building apps, gzipping backend and frontend into one tarball, then either:
- Ask my "release person" to copy it into the Windows server drive for test or production
- Run my own "release script" that scp's it to my Digital Ocean droplet and tells pm2 to restart the production application
My projects email me when something crashes in the back end and I run sentry.io to see what's gone wrong in the front end.
Why I find this to be a great developer experience:
* Simplicity. One language, easy to share things like e.g. validation between FE and BE, minimal cognitive burden when context switching; small apps = simple code; simple release system means I can get new features or bug fixes to users extremely fast with minimal fuss
* No CI pipelines or DevOps time sinks: this is effective because I'm a single developer; I also work on projects where a solid CI pipeline and infra as code adds value, but these things can also slow you down too
=====
In other words, what I feel makes me effective is using a modern language and ecosystem, but deploy it with methods from 10-15 years ago. :)
- Should not need an IDE ::: The system should be able to be developed without depending on a particular IDE or set of proprietary build tools.
- CLI tool-chain ::: The system should be able to be built and deployed using CLI tools, preferably open-source.
- Versioned deploys and Rollback ::: Each deployment should be versioned and rolling back should be fairly trivial (when things break this needs to be easy).
- Modular development ::: pieces of the system should be able to be developed individually without compiling/building the entire project.
- Poly Repositories ::: I've found mono-repos make every bit of code highly-coupled. CI tools like github actions, makes poly-repos much easier to manage and improve separation of concerns, dependency management and modularity of components.
- Feature based folder structure ::: Grouping source files by feature, rather than by file type.
- Design components for testing ::: Testing should be considered during development of components, then integration of testing later is much easier (decouple database logic, dependency inversion etc.).
- Encapsulation of libraries ::: I personally prefer that most external libraries are encapsulated within wrapper classes, in order to insulate them from directly touching different parts of the system (ideally)
- Cross-platform should be trivial ::: Web-based applications easily achieve this, but so do many scripting languages etc. If building for different platforms is unreliable/impossible than that's not ideal.
These things vary in importance from person to person, but they're important to me.
I've learned to actively loathe getting started on a new feature for one of my sites. The typical process starts by trying to make a simple change to the codebase, only to learn that some tool needs updating (who knows why), but only after digging around for half an hour trying to figure out why something simple doesn't work. I then try to update the tool, but the update doesn't work, because something else has changed on my dev machine, making the update incompatible. After trying to update everything for a couple of hours, I sometimes manage to get the development environment working again, at which time I actually start coding. Sometimes I just give up and try again in a couple of months.
In the good old days, I would just open a code editor and edit a PHP file, then upload via FTP.
If only it were that simple now. My ideal developer experience would be to simply be able to open my computer and start coding – even if I hadn't worked on a project in a few years.
The language has evolved tastefully without breaking away from the past in drastic(pythonic) ways. Frameworks like Laravel still continue to evolve in a rapid pace than its contemporaries in other languages, bringing in support for every new advancement like webpack, OAuth, etc.
Text editor support is also rapidly accelerating with LSP as a part of the core runtime. PHPStorm is still a beast of an IDE. Composer is in many ways an ideal package manager, a cross between the ease of bundler and local package scoping of npm.
The runtime evolves at a rapid pace, with performance improvements in every release and the upcoming JIT.
Most importantly, the development and deployment story of PHP is still easy as ever. Unlike other modern stacks that require arcane version manager, virtual environments, docker layers, etc, the LAMP stack is still the one script environment creator that requires nothing more than a working Linux distro. The WAMP one click installer still works on Windows without any Subsystems.
Emacs+C#+omnisharp is pretty darn close to my ideal development experience. My Emacs config is not particularly long nor particularly involved, and in fact one could replicate my C# setup with less than 10 lines of config code.
Highly recommend.
Basically any new project (unless requirements show that it needs something else but 90% is OK) starts out as a Java or Kotlin Spring Boot project with a Postgres database. This is super easy to setup locally, provides most things out of the box and the Java/Maven ecosystem has stable libraries for everything else.
When it's time to deploy this I package the project as a Docker container, write a Kubernetes yml config and I'm good to go on most cloud providers.
I focus mostly on making sure there is as little difference as possible between me clicking "Run" in the IDE, and the packaged project running in Docker. Usually the only differences are ENV variables for configuring database and other dependant services.
- flutter doctor: checks your Flutter installation and shows missing platform dependencies, if any.
- Dart is a very nice statically typed language with a decent standard library.
- Flutter has A LOT of prebuild components for almost everything you need and makes it easy for you to build your own by composing existing ones.
- Built-in code formatting tool (dartfmt) and testing framework
- flutter.dev has everything you need to know in one place.
- pub.dev is a central place for all packages. dartdoc generates beautiful API reference pages for all packages on pub.dev and you can use it on your own packages as well.
- It works on all devices, all android 4.1.x or newer and iPhone.
I think it's the best tool if you want quickly build a nice looking user interface.
1. I write code in an editor, it auto lints and formats to standards of project.
2. On save, whatever is needed to build and test is automatically run.
3. After repeat 1-2 and ready, commit code and create pull request.
4. On commit, integration tests run and one-off environment to smoke test is created.
5. On accepted review and merged, auto deploy to production or next release.
Based on my experiences, here are some ideas regarding a hypothetical ideal developer environment - some technical, some cultural:
- A supportive and responsive team who help each other to get valuable features developed, deployed and maintained
- Thoughtfully-written test coverage that allows for code evolution, while providing reassurance that changes are correct
- Local, test and production environments where deployed code behaves identically or near-identically
- Languages and API documentation that are accessible, expressive and composable while remaining straightforward to reason about
- Development, deployment and operational tools that lend themselves well to automation so that frustrating and error-prone manual tasks can be reduced
- Rapid notifications regarding problems encountered by users -- ideally only occuring infrequently, thanks to high code quality, and implemented in a user-privacy-preserving way (to avoid developer anxiety regarding imagined or real lack of organizational respect for users)
- Code review (for various social and educational reasons, as well as improvement of code quality)
- Human product feedback, in terms of quality assurance and also genuine user feedback
- A high-motivation and low-pressurization work setting -- with a sense that the delivered software is genuinely providing a net benefit and is able to anticipate and respond to harms and ideally prevent them in future
- The time and team approval to investigate bugs and contribute the discovered fixes upstream outside the organization
It also strikes me while writing this that software may be considered easier and/or more comfortable than other careers.
While it's good to strive to find further improvements, it's worth pushing for other employers (and perhaps industries?) to do the same.
- typechecked, but the types get out of the way; "var" and intellisense fill them in for you. It also shows you what types the function arguments should be and autosuggests objects of those types
- functional when you want, but not when you don't: LINQ et al, interlinkage with F# if you want to get really functional, now immutable record types. Lambdas.
- wordy enough that you can see context, but Intellisense means not having to type it out
- smart refactoring (paid-for Resharper)
- debugger when you need it: run test case. Wait to hit exception or breakpoint on failed assertion. Inspect values. It's often immediately obvious where the problem was.
- CPU and memory profilers readily available and well integrated.
- standardised on Nunit with Nsubstitute for testing: bit wordy, but with a bit of thought we're now hitting 100% line coverage on wholly new code.
- portable ish binaries with Mono
- package management system is mature. (Wart: packages are at the "project" rather than "solution" level in VS, so you need to do extra work to ensure they're all the same version)
The only real downside is the build system (MSBuild) is pretty poor, badly documented, and not easy to use for other things than C#.
For the future? "Software components" have never quite delivered. Package management is clearly the frontier here.
Language interoperability is another: it's still astonishingly hard to combine languages within a single software artefact unless they're C and C++ or similar things that produce platform-native binaries. Proliferation of language runtimes makes this worse, not better. On the other hand, the two frontrunner runtimes of C# and Java both have problematic owners.
I fundamentally couldn’t agree more that it’s a shitshow right now. Everything could be better. Namely:
- Typescript + monorepos is a total pain in the ass
- react-native-web is the way to write apps if you want to go cross platform, but there’s a ton of sharp edges and no great UI library to write components more cleanly
- Still no great, obvious state management system for frontend
- We’ve been gluing together a setup for Kubernetes, docker compose (locally), and CI/CD on GitHub. It’s a ton of code even while keeping it simple. Too much to list here. We’re using Rio for some of it, which starts to get some of the DX better
- Hasura and graphql and then on the frontend the biggest upgrade I’ve had in years is gqless (https://gqless.dev). It’s a bit early, needs a lot of work, but fully typed queries are just incredible
- Just endless amounts of cross browser issues, polyfills necessary for various browsers
- Obviously tons of time spent getting webpack to play along.
- Getting your tests to work just like they would in the browser took us quite a lot of iteration, we use a wide variety of testing tools that took time to figure out
Honestly, it’s all bad. The bright spots are Chrome dev tools, React Refresh, gqless, Hasura, and our UI kit which is building on react native but adds components ala SwiftUI (VStack, HStack, etc) that then statically extract to css at compile time.
I do like the thinking behind “Rome” which basically wants to pull everything together and vertically integrate. I’d almost go further and just white label a whole stack just like ours. Including CI/CD, monorepo, etc. If we could pause in 6 months or so and just extract everything we’ve built into that, it’d be a great template.
There is so much more detail on each layer of a system that there is no way you can just write piece of code and put it to production.
Ideal situation would be if developer can just write code hand it over to test people to check then to ops people who can scale it and secure it. But we all know how it ends up. So even more ideal would be when you write code upload it to the cloud and it just works. But we know it going to cost loads of money.
If there is no silver bullet, try to carve out a little niche for yourself where you mastered own tools and stick to i.
I keep reading this on HN and I am surprised every time. It is so much easier nowadays to develop software than it used to be. Back when I started out there was no HN, no Stack Overflow, no online software developer community that I had access to. I had to learn everything from books and often had nobody to ask. It is so much easier nowadays. I honestly would love to understand what it is that makes it feel hard? Does anybody have a good insight as to why?
I miss my Vim bindings, and I wasted a little bit of time trying to get HMR to work with parcel, but other than that it really feels like the tools mostly just get out of the way and let me build my idea, and when I'm done coding I think I'll be happy to just leave it on glitch. (I paid for "boosted apps").
My recommendation is to choose boring technologies that are widely deployed so that people will have to support them for decades to come. If there isn't a mature, well-supported option in a space, it's better to roll your own than to spend a bunch of time learning a technology and writing code, and then have to relearn and rewrite in 2 years when that technology is no longer supported. The bigger and more complex something is, the more you should let it get boring before you commit to it.
Here's what I'm using:
* Django
* Django REST Framework
* Celery
* React/React DOM
* ImmerJS
* Postgres
* Redis
* Nginx
For the most part, if it's not on this list, I try not to use it. There are other libraries I'm using, but nothing I would recommend.
There are a lot of things I hate about Django. But it's a boring technology and that outweighs the other concerns. It works and I have no doubts that it will continue to work well.
The one thing on this list that's not a "boring" technology is ImmerJS. This is not a complex technology, so I'm a bit less worried about adding it to my stack. And it allows me to avoid the global state that Redux or similar tools force you into[1]. If a better solution emerges, I don't think switching from Immer will be very difficult, and if Immer loses support, I don't think there will be much difficulty in continuing to use it.
[1] Yes, I understand how reducers work. If you don't understand that reducers are a way of pulling out one part of global state, you do not understand how reducers work. Sure, reducers make using global state less painful, but introducing complex tools to deal with problems created by your other complex tools is not a good strategy.
Generally, it's all about reducing friction and preventing human error where it's cheap to do so.
In the same way, something hacked together by your average developer now is a lot more stable than some "production" run 10-15 years ago, even if it's just because of the quality of the infrastructure that exists.
Nothing more than that.
Perhaps the complexity increase when we start giving funny names for simple things, opinions, personal preferences...
Countless hours can be wasted arguing what "deploy" is, what an "artifact" is, "container", etc.
Boring is better.
You see as soon as you make it easy to do X, everyone does X, X becomes cheap, there is no business in making X anymore, you need to do complicated thing Y.
My ideal devx stack(some parts exist but some don’t)
1. Heroku like deployments everywhere in a Unix like standard fashion. If the standard exists, I’d not worry about vendor lock-in and can choose the right provider for my scale/cost etc. I’ll also be able to have the same workflows for private DCs , dev setups etc without running huge bills.
2. Heroku CI/flow/pipeline, again standardized so I’m not stuck with one vendor.
3. GitHub + VsCode (or vi or emacs or pycharm) delivered as an offline first service. With templating capabilities so you can onboard new team members with a click.
3. Expo.io like capabilities across platforms. I get it that it’s already available for iOS, Android and web. But what if I have a native app? What about a server I wrote in c/c++? Docker probably. But the updates are still not handled for me automatically.
4. As a historically backend person, I find it hard to believe it took this long for the front end world to get to the component framework. I’d like to be able to create frontend pages by just pointing to an openAPI crud spec. I want to be able to add special buttons or forms in one line (no more) by just specifying a non-crud openAPI spec. We are almost there but not quite.
5. Since Saas is the future, All user management, subscription, engagement tracking, support, Customer pipeline etc should be a few line setups.
So I’d get up one day having dreamt of a new feature, walk to my home office in pajamas, code up the backend, specify how to expose it in the frontend, add a few test cases and click submit. It goes through testing locally, in staging, to production, gets distributed a set of people, and sends me some data on how good the dream can be by the time I finish my coffee. If I am happy I click “roll out “ And the entire world benefits from my dream.
Some companies have painstakingly built this stack. One man shows can actually do this fairly easily but mainly because the User base is small. But nothing that works for medium sized companies.
Too much to ask?
rust, c++ For some high performance Python might be good to know just because so many DS things are written in those languages. Scala/java/c# for something robust but verbose e.g. fintech It’s really depends on industry.
Building, both artifacts and tests, should be single commands. That might mean you need to write a script that does the "cd into a directory, cmake .., make, make install" dance, but it should be handled.
Dependencies should work, should not conflict with system dependencies, and should be fetched if not already present. Hi Python!
Good IDE support: IntelliJ has some great features, I'd like to use their stuff. But some people want to use other IDEs or editors. Maintain project files for common ones.
Self-contained PRs. Keeping PRs small is all well and good, but having PR A depend on PR B and C and D getting merged in the right order makes review much harder than if they were all just stuck in one.
Must work on Linux, Windows and Mac, at least. Preferably also some BSDs.
Documentation, with all of the following: An introduction saying what your project does, tutorials on how to do intended tasks, how-to guides on solving detailed issues, explanations with examples of how things are used, and a comprehensive reference of what can be done. Divio has a good article[1] about this, though it misses the need for an introduction while providing one itself.
Strong types, with good type inference. Dynamic typing is nice for scripts, but not for full-on programming.
Good safety around memory issues. GC or Rust-style ownership based will depend on application, of course.
Interoperability with different languages. Especially an issue is building multi-language projects.
As an embedded dev, the hardware should be debuggable. Provide a damn JTAG or SWD port. Provide a GDB server or OpenOCD plugin. Provide test points, and a dev board with a damn schematic!
Have your datasheet actually describe the function of the chip and how to communicate with it. LTC (now owned by Analog Devices) datasheets tend to be great examples, try to be like LTC/AD. For example, see the LTC4015 datasheet[2]. It provides example application circuits, clear pin configurations, detailed typical performance info, a nice detailed block diagram, I2C protocol info (because that's chip specific), functional descriptive text, equations to calculate the needed supporting component values, operational state flow charts, detailed component selection procedures, PCB layout considerations, a full register map, and a recommended solder pad layout. Too many datasheets lack too much of this info.
[1] https://documentation.divio.com/ [2] https://www.analog.com/media/en/technical-documentation/data...