Rethinking the IDE for the 2020s
movingfulcrum.com
movingfulcrum.com
One example: "The IDE should ask for the Github org eg, github.com/astradot and it should create a single project that contains all the repo as modules. It should then manage lazy-loading/lazy-checkout or whatever is needed to give me a seamless experience browsing the code of my entire org."
Like (I strongly suspect) a majority of developers, I work in a large monorepo. There are 400+ other repositories in the same GitHub org. 99% of them are small projects I'll never touch. I wouldn't want my IDE to go anywhere near them.
Hundreds of microservices”
Can people with expertise in this situation speak about how typical it is? I guess if you have all those services then you need your IDE to help - but surely this isn’t super common? If it is, what sort of size of micro service are we talking here? I’ve worked in orgs with 3M line codebases, and I’d struggle to find a hundred ways to partition the code naturally.
* Each team (let's call it eight engineers per team on average) typically managed a few services.
* Services were typically ~thousands of lines of code to ~tens of thousands. Rarely, there were very small services that were hundreds of lines of code. There was a giant service -- the original Rails app -- called "Monorail" that had millions of lines of code, but was actively being dismantled. My understanding is that there is now a code freeze on Monorail, and the only changes allowed are changes that remove code from it and move it to a smaller service (either an existing one or a new one).
* Services communicated with each other over HTTP or Kafka, typically using Thrift, although also sometimes using JSON. Airbnb had an in-house "service mesh" (developed before the term service mesh existed) that abstracted away individual machines and was capable of operating at the HTTP or TCP layer.
A few classic examples of mostly-single-responsibility services:
* Prometheus (which I wrote) abstracted away reverse geocoding and correctly caching and manipulating results from geocoder APIs.
* Medusa abstracted away ranking and filtering listings by date/amenities/etc.
* Micasa abstracted away basic CRUD operations on individual listings.
Airbnb intentionally used codenames for services rather than calling them by what they did, which I wasn't a huge fan of; I forget most of the codenames now (and hardly anyone knew all of the codenames offhand even at the time). Some other example without the cute names were the pricing recommendation service (used to recommend prices to new hosts), the calendar management service, the experience CRUD service, etc.
Data:
- Canonical data repositories for each of: order, transaction, customer, feedback, geography, privacy opt-in/out.
- Hadoop SQL facade.
- Support contact analytical service for a particular type of issue.
Business operations:
- Core order fulfillment service (orders populate into repository when complete).
- Support contact operational services: ingestion, routing, and auto-resolution.
Product infrastructure:
- Machine learning model serving engine.
- Map drawing service.
- Translations service.
- Dynamic configuration service.
- A/B test service.
- Server-Sent-Events hub service for our mobile apps.
- Facades for each of: voice, SMS, mobile native pushes, email.
- Marketing campaign service (dumber but more convenient facade to the previous).
Basic infrastructure:
- Column store.
- Secrets service.
- Cache service.
- Blob storage service.
- Workflow engine.
- Timer service (technically a subset of a workflow engine).
- Message queue.
Each one of these is backed by a team of 2-10 people. I have been inside 2 or 3 of them to fix bugs that affected me.
Microservices didn't become popular because the code could naturally be refactored that way, but because they enforced an interface boundary that worked better for mid to large sized organizations with multiple teams of engineers and levels of management where the communication overhead is much higher.
Each team has developed it's own way to work with it's subset of services - I doubt every team across every org could figure out how to run everyone elses domains to even make checking out the world a useful exercise.
As a long term corporate exercise, maybe that would "be awesome", but not trivial to do and PAINFUL to support and stay on top of over time.
We had a hard enough time keeping test suites up to date - I can't imagine trying to keep our portfolio "runnable" for everyone else.
I'm not sure whether it was really worth it for us, but it did solve that problem.
Granted there is effort in learning ELisp in the first place, but now that I'm comfortable with it, I find myself able to adapt to these changes quite easily while many other developers have to wait on big feature releases from their IDEs, use hard-to-automated GUIs, or heavyweight IDE APIs to develop "plugins" to modify behavior.
The available interface should be the same as what it is for plugins: https://plugins.jetbrains.com/docs/intellij/psi-cookbook.htm...
These should be useful imports:
* com.intellij.psi.JavaPsiFacade
* com.intellij.refactoring.RefactoringFactory
If someone knows better, happy to be educated on this!
https://www.jetbrains.com/help/idea/ide-scripting-console.ht...
Tools should help you do the right thing. They should not be a painful bludgeon against other devs. Enabling fast and easy end to end testing is only helpful.
There is no reason that making that easy to do will cause tech debt. You already have other means to your services cleanly versioned and compatible, such as tests. Making things environments easy to run locally doesn't change that.
You're saying that a desire for when something gets worked on should trump any other design decision? "Want at the same time" informs separation of concerns?
You make services in an vacuum without considering the stakeholder/consumer of your service? You've never planned for a service in your org you consume to gain functionality because doing so would mean you should implement that functionality yourself in a service you own?
"How often will we need to change this and what will that be like?" is usually my top design consideration after "will it work?" So yes on that one.
Here is what I think IDEs need to do different in the 2020s:
- configuration needs to be in human-readable configuration files, not obscure XML configs that can realistically only be edited through UIs.
- how to build the project needs to be completely decoupled from the IDE
- compilers and language services need to be separated from IDEs. LSP and automated refactoring tools using the same infrastructure as the code that's doing code completion makes sure that everything is consistent
- emphasis on input latency is needed for editors to feel snappy. Lots of full blown IDEs are not great for editing text.
edit: typo
See also https://build-server-protocol.github.io (but it doesn't seem to get much traction yet)
- We no longer want code running on developer machines. We're actively working to embrace remote execution for everything. - Repository boundaries exist for a reason. Why are you modifying two repositories at the same time? - We think collaboration is a good thing. Live coding allows for pairing and troubleshooting. It's great for knowledge sharing and for getting new developers up to speed.
Upvote the issue if you wanna bump up the priority https://youtrack.jetbrains.com/issue/KT-45087
Managing dependencies, at build and run times, internal and external, seems to be the prominent pain point. As far as I can remember, it has always been and it cannot be solved in a single simple way.
Things have gotten "better" (ie at least there are tools and practices) with the omnipresent git, cheap VMs, CI, docker, kubernetes, etc.
> Refactoring so far has really been a single repo feature. But what if the code you are refactoring is called by code in 100 other repos in your organization? What if those repos are not even checked out locally? The modern IDE needs to evolve beyond single repo operations.
I hesitate to either call to Hanlon razor or accept that tools can help, further than basic monorepos. I don't see any valid ways to manage this with external dependencies however.
Cloud IDEs provide value for specific portions of the market: 1. Training 2. Remote contractors in secure environments 3. Support 4. Classrooms 5. Vendors who want embedded dev envs in other products 6. Open source clones / snippet evaluations
Codenvy was strong in the embedded dev envs for other products. When you look at the various vendors that have emerged like Coder, Repl.IT, among others, they have a tendency to specialize in one of these areas.
That is quite different from the first generation cloud IDEs which tried to compete with classic desktop IDEs.
There have been some weak attempts in IDEs (e.g. auto generated UML), but it's not really useable. Closest seems SourceTrail but that has many issues ...
I wonder, are some people writing (and sharing these things on HN), not to share some insight on some subject but to have something to point at during interviews?
I do need to pair program remotely, and collaborate on design docs. Collaborative editing isn't like a 24/7 feature that you need to enable, and I don't know why the author thinks those are the reasons that they're valuable.
I'm mostly waiting for something to more easily interact with the AST than pure text (like something more of a tree view).
Think more easily (that's the key) collapsing bits of code, dragging them around and deciding whether they're active.
This article hits most of the nails exactly on the head, at least from the perspective of large corporate environments; I doubt any of these apply to small startups (and if they do to yours, something has probably gone very wrong). Nuclide handles these issues in fairly interesting ways:
* FB built their own incremental, caching compilers for several languages that Nuclide is aware of, so that typechecking and rebuilds are effectively instantaneous even across massive codebases.
* Nuclide integrates with FB's massive cross-repo search service, BigGrep, so that you can find references to anything.
* Nuclide's version control UI is phenomenal, and is aware of multiple repositories existing, which ones you have checked out, and integrates with their in-house version of Phabricator (a code repository/review tool similar to Github). I literally never learned to use Mercurial while I was there. I just used Nuclide.
However, there's one major difference between Nuclide and the vision that this article lays out: remote vs local code checkouts. Nuclide ran locally, but it used remote code checkouts, and your code ran on the remote, not on your local machine. I think the reasons and benefits were compelling:
* Massive repositories take up massive amounts of disk space.
* Massive repositories take massive amounts of time to download to your laptop, and if you're working in a large corporate environment, they also take massive amounts of time to download recent changes since there are many engineers shipping commits.
* If your machine gets hosed, you can spin up a new one quickly; in FB's case, it took seconds to get one of the "OnDemand" servers. If your local machine gets hosed... A trip to IT is not going to be as easy.
* If you run into issues, tools engineers can SSH directly into your instance and see what the problem is, fix it, and also ship preemptive fixes to everyone else. That would feel quite privacy-invasive for someone's local machine.
* Many employees enjoy being able to take their laptop with them so that they can work remotely e.g. to extend a trip to another country without taking more PTO. Laptops aren't great at running large distributed systems.
* Even some individual services (ignoring the rest of the constellation of services) are impractical to run on constrained devices like laptops, and operate on either "big data" or require large amounts of RAM.
* Remote servers can more conveniently integrate securely with remote services than laptops or desktops.
* Having the entire codebase stored locally on a laptop or desktop is a relative security risk: if it's in a centrally managed server and a laptop gets stolen, revoke the key. If it's on disk, well, hope the thief didn't get the password? Or in FB's case, hope the thief isn't an APT/the NSA and has backdoored the laptop's full-disk encryption? And it's not just laptop theft: a disgruntled employee could intentionally leak the code -- or in Google and Anthony Levandowski's case, sell it to a competitor through a shell company. If everything is stored centrally and local checkouts are extremely uncommon, you have a lot more room to automate defense against that scenario.
Overall I'm a big fan of running your code on remote devservers rather than on local machines once you get to scale.
Its not hard to set up a multi-project view in Intellij. There are a lot of choices for build systems that will track cross repo builds. You can use something like Docker Compose (or several other options) to run many services locally.