First do it, then do it right, then do it better
twitter.com
twitter.com
Thus, lots of stuff that falls in the "Important, but Not Urgent" category of the Eisenhower Matrix end up never getting its proper development time. One could argue "well, then maybe they weren't actually that important, were they?" but I'd reply that usually the criteria to define something as important is measured with growth potential, and that's the wrong bar to use.
That's how we end up with "we'll build it in Electron for the time being and later will rebuild in proper native apps if the idea works" ends up being still Electron 10 years later. Or how "we'll make our own controls and later worry about accessibility" turns out never worrying about it.
Optimizing as step one is a very good way to not ship on time and miss opportunities to competition.
what gets considered important are things that hurt them rather than their users. In many ways it's an abuse of users.
But when 3 of these bulky apps are eating the whole RAM and no more software can run because of them, it's the user, especially the not very savvy user, the one who usually assumes their computer doesn't work any more for modern software and they need to incur in the effort and cost of acquiring a new one.
Electron is a fine way to test a market, but it is only financially viable to use long term (such as done by Slack, Discord or Spotify) because it externalizes the actual cost to its users.
For an app that is open-use-close, it's ok and I see no issue. But for apps meant to be constantly running in the background (like a music player or a chat app) I think Electron is almost a sin against its users.
But they’ve determined that this cost isn’t meaningful enough to write performant native platform specific versions.
That obviously sucks for your users who really need it, but if there aren’t many of them, the site/app/whatever will just be hard to use for them, probably forever.
On the initial use of an unfamiliar acronym within a document or a section, spell out
the full term, and then put the acronym in parentheses.
... then goes on to lecture people about making things understandable... not even mentioning wtf "a11y" is supposed to mean is kind of taking the piss. :/In a non-tech specific community, I wouldn’t use these abbreviations, but I see no issue with them here.
thank you
I hate "ally" thing so much >_<
After all the phrase ‘there’s nothing so permanent as a temporary repair’ comes from construction.
I think the difference is rules and licensing were created around physical repairs and construction because of the human tendency to ‘good enough’ it.
And to be fair software that has the same safety importance as bridge sturcutural calculations does have a level of scrutiny around it commensurate with its importance, see NASA and their caution and flight / avionics software for aircraft etc.
If you're a company with a $27b valuation releasing an Electron app, then you're just a shite company. How do you have any self respect at that point. I get being a small team without subject experts in native apps and just need to get something going. If you are a $27b valuation small company we might continue the is Electron still the right choice conversation. I'd also be very curios what your app is doing that a small team can operate it and still be valued so highly. Otherwise, you're just a shite company making shite decisions and have no self respect.
However if you're interested in why this happens you need to acknowledge there are legitimate tradeoffs between going full native and Electron at any scale. Specifically, feature/UI parity and speed of development is higher with Electron. Deciding to retool your whole engineering org to optimize for highly polished native apps is actually a pretty risky decision once you get into this position at scale, regardless of how much engineering cred it generates HN and other highly technical/UX focused circles.
For most people, the software is "good enough." That doesn't mean that it's engineered in the best way possible. That just means that the business concentrates on other concerns (some simply about gaining more market share and profit).
I'm always in pursuit to write the best quality code that I can, with performance in mind. I also work for a small software company where I have that luxury, and also the drive to practice outside of my salaried hours (because I enjoy it, not because I feel I need to). I would feel terrible if my clients were complaining about slow performance, and I would find a solution that works within my constraints of having other client work to perform. Not having to support thousands or millions of users with my software makes it a lot easier to work on a rewrite than needing to worry about every operating system and configuration that is out there, along with new bug reports that need to be addressed.
But rereading what you wrote, I do think that my paraphrase -- while certainly harsh -- is not inaccurate. You were pointing out, quite correctly, that choosing to use something like Electron is choosing a particular tradeoff. That tradeoff is to reduce development costs at the expense of product quality.
I'm not saying that's always an inappropriate tradeoff, but we should at least be clear about what the tradeoff is actually about.
On a more nuanced point, tradeoff is not strictly cost vs quality, it's also about velocity and consistency. The latter especially can have a huge impact on the perceived quality for common users, so the tradeoff is not as black and white as you want to make it.
How many companies have $27billion+ valuation and are not 'shite' software companies?
I'm just wondering about this, because almost all the big companies I know write shite software... in fact it seems has nothing to do with how 'shite' your application is, but if it has the features the users want.
Is there a reverse correlation? That if you're an investor you should shy away from companies writing 'non-shite' software because they aren't focusing on deliveries?
Because they have CFOs and other bean counters at that point, and there's just no good way to convince those people to approve spinning up new teams (or reskilling the existing one) to rewrite the application "properly" across several platforms.
It's like comparing "$$ for new feature development" (will move us forward) with "$$$$ for rewriting the application to be more efficient" (with uncertain benefits).
Those could - but don't have to be - valid arguments for using it while still retaining self respect, e.g. making an informed choice on what is best for the project one is working on.
Most users accept it because they have no better choice. If an app is terribly slow but a lot of online communities and friends use it, what are they gonna do, just not interact with others? You want to play recent Nintendo games but don't want to regularly replace the controllers due to an unfixed issue that affects roughly 50 million people and has a perfectly working solution for over 20 years? Too bad. But I guess Nintendo calls it acceptable for most users because it's not quite bad enough that people stop using a product they paid for.
People are already voting with their wallets and they're overwhelmingly voting for more exploitation, partially "helped" by the manipulation systematically employed in the industry that's already worked wonders for classic gambling. And Valve investing in Linux gaming had nothing to do with the size of the target audience - luckily for us.
That's a description of the problem.
This thread is people who ship products vs people who ship engineering.
Usually looking at their last paycheck.
I don't personally agree with it, but, to some degree, this comment seems tone-deaf.
People keep paying them to be so-so.
It's not that complicated. That's a new-ish capability and was not an option when the apps being discussed chose Electron (for their desktop incarnations). It's also not applicable to all macOS systems (as you already noted) out there given that it requires M1-M3 Apple devices. They'd still need to support the older macOS systems while also working out the issues on newer systems. Or they could maintain one solution that works on both.
To be clear, I'm not saying that a developer culture shouldn't strive for this, but these are large businesses and are out for that dollar, and neither seem to be run by developers that would call for a rewrite.
No, but they seem to be run UI people. They can justify doing a rewrite of the UI, but not the core? Not one person that I interact with using Slack appreciated the UI changes
I'm not sure if we ever get to the point where developers need to start worrying about performance for environmental purposes, that we'll survive if the performance impacts have been measured properly. I'm not trying to be depressing, but I just don't think that it would ever happen until it was too late. Maybe there would be a minority left of society to do this, but that would be building back society. Doomsday scenario. I don't think "we" are smart enough to deal with any catastrophic situation until it's too late.
This sort of thing is another example of our collective race to the bottom.
I don't agree.
Most people don't actually know any better, to be able to care. That includes not just normal users, but programmers, web admins, team leaders and managers too.
They never had to unload a TSR because there wasn't enough conventional DOS memory available. They never used Win3.10, where even the button light/shadow colors could be changed, yet fit into 1 MB RAM and 20 MB disk. They never browsed via 3KB/s dialup. Many never saw a website 1.0 without JS. Of them 99.999% never saw a 64K intro/demo. They don't know it's possible.
> If people did care, you'd have someone writing a highly optimized chat/voip app from the ground up
That does happen, rarely, and even then, it doesn't change the situation.
1) Very very few people are capable of writing apps. Out of them, very very few are capable of writing apps, optimized or not, that don't import the entire internet as a dependency. That's because that's how they were educated: "don't waste time rewriting code", "you'll repeat the mistakes", and other BS arguments that lead to nodejs and other monstrosities.
2) Those very few people are the same ones that actually wrote Discord, Slack, Teams. Most of them want to finish quickly and jump ASAP to the next big fancy project that caught their interest. So they import the entire internet as a dependency instead of writing again a 2-line function. These are the people that didn't care.
You won't see anymore people like Christian Ghisler who write and maintain some piece of software for their entire life.
3) Someone recently wrote a Windows terminal app faster, smaller, better than the official, just as a tech demo. Most people (99%) won't find out about it. I'm sure there are Teams alternatives. Nobody finds out about them because Google and M$ control what everyone sees.
“Do it right” should always be the first goal. Then you make concessions to make sure it works in the flawed reality it needs to operate in.
A classic example from back in the day (maybe it’s still this way): don’t just design your webpages for IE. Write the markup and stylesheets as they ought to be, then amend as necessary to make it look correct for each browser’s quirks.
It’s extremely depressing working with “senior” engineers who’ve spent an entire career with the above mentality, who have missed out on any chance at ever learning how to actually engineer software for reliability and maintainability. Their inability to do so reflects on a lack of practice rather than some sort of fundamental impossibility. Which sadly seems to be a widespread misconception these days.
If the problem is hard, you have to start thinking about it early. But every day you've thought about it a little without committing, you have a little more information about how it'll feel to take each path, and how it's likely to affect your operations people and customers.
Also Observation Bias may cause you to read that one article that explains why one of the choices seems like a good idea but is a trap. Or why you definitely should or should not use the latest major version, because of some change for the better or worse.
Frustratingly, some people see any discussions about such things as non sequiturs, distracting them from today's problems.
Worth noting:
Most decisions are 2-way doors. Very few decisions are 1-way doors. It takes experienced folks to identify true 1-way doors and apply the brakes. Having a culture of thoughtful document reviews, for example, gives space for people to identify 1-way / 2-way doors and push back. Having institutionalized knowledge gained from 20 years of running the largest public cloud provider helps in identifying 1-way doors in software development too.
All of that is to caution... yes, Bezos says useful things, can you take it and apply it to your company? Maybe. Do you implement / have the rest of what made it work well for Amazon too?
So he basically says "It will either rain, or it will not rain".
That some decisions are more important to get right than others (that "the dichotomy exists"), is just a trivial observation, the kind that people like Bezos make to appear insightful "technical leaders", but which are ultimately empty, amounting to "some decisions are important, others are not". Gee, thanks, Jeff!
The interesting part is knowing which case is which, or advice for that - which the above leaves out.
This is true, unless you also follow the "throw away your first draft" process. If you do that, then you also throw away all of the duct tape and bubble gum you put in while figuring out what you're actually doing.
In both cases if originally building in Electron was a substantial productivity boost then it sounds like it was the right choice.
I worked this way with a super strong business PM. Each iteration was small but we measured everything and made sure it had impact. Every feature was built properly, IE tested, refactored, typed etc. It made our pace more steady. If something didn’t have an impact we tried to understand why, incidents were reported and properly remedied. Still the most solid way I’ve worked.
The real revelation for me though is the reversible decision, to the point that for really reversible decisions, I can be very averse to us spending any significant meeting time on it at all. There are 6 of us here, let's not waste man-hours on something we could as easily decide with a random number generator. Move on to something more delicate.
The technical issue here is that the protocol is closed, not that the client is fat. So someone in a RAM-constrained environment can't choose to make different trade offs. But the protocol being closed, while annoying as a user, is definitely a strategic choice.
It's tempting to believe that just by dropping the "discover what you need to do step" and you'll get enough time for it and make the thing a single change you can plug on your Jira. It's also delusional. A blatant lie people have been repeating to themselves for half a century, while fully knowing it's wrong for the entire time.
The problem is that it's very difficult to articulate that difference. This is a failure of language (and social norms), and it has to be recognized by both the speaker and the listener before it can be accommodated.
2. Then make it beautiful
3. Then make it fast
4. Rinse and repeat
Suffering-oriented programming (2012) — http://nathanmarz.com/blog/suffering-oriented-programming.ht...
Listen to the customer so you CAN:
-- Make it fit for purpose.
-- Make it fit for use.
If the above fails,
-- Make it fit for marketing.
-- Make three envelopes.[1]
Sounds like your codebase will be full of shitty half-backed half-non-needed "features" with a lot bugs, legacy, and misdirection.
> then do it right
Sounds like your codebase will have a lot of hyped, now-dead, trends-of-the-moment frameworks while your team keeps arguing what's "right".
> then do it better
Sounds like your codebase will have a lot of rewrite in the new hyped, not-yet-dead, trends-of-the-moment frameworks while actual business logic will be ignored.
In my experience, this is the worst advice if we are talking about software engineering. I would advise the opposite: "Is this needed? really needed? nerd out on why it's needed."
The opposite advice has merit, but you can’t take it to the extreme. Better to build a MVP in 1 month than to spend 6 months doing user research and then another 6 months building a MVP with perfectly performant and optimized code
POC code doesn't belong as a permanent codebase.
>> then do it right
> Sounds like your codebase will have a lot of hyped, now-dead, trends-of-the-moment frameworks while your team keeps arguing what's "right".
Doing it right should include a framework. I'd rather use a framework that is dead in a month than write 10s of 1000s lines of boilerplate to make my own. ASP.NET and Spring come to mind as modern reliable frameworks. Even angular is reliable even if not popular.
>> then do it better
> Sounds like your codebase will have a lot of rewrite in the new hyped, now-yet-dead, trends-of-the-moment frameworks while actual business logic will be ignored.
Code should be considered disposable when it has outlived its usefulness. Even if that requires a rewrite. I've maintained classic asp websites and I have rewritten them in modern frameworks. Projects are not immutable. They are only as useful as they are until they are not. Then they die or get rewritten.
In almost every company I've seen "Is this needed" is always followed up by some c-level saying "Of course it fucking is, we've sold the product for $X million to $Y company and now we need that feature working"
HN has a fair number of commenters that live in a dream world where they get to implement the features they choose, but for the vast majority of programmers it's going to be the features sales chose.
Often the "fast" part is very intertwined with the "right/work" part. You can make it work/right and then realize you designed the core data structures completely wrong for performance. I know, I've made that mistake terribly before where I avoided performance until a year after a project was in flight, only to realize the fundamental API design actually made it impossible to fix. Had to basically start from scratch.
Of course it depends on if performance matters much, but it often does.
It's not about avoiding making it fast, it's about prioritizing. There's a probably apocryphal story from, I believe, The Psychology of Computer Programming (Weinberg) where a mainframe programmer opposed a new program because it wouldn't be as fast as theirs. Except their program produced garbage results, and the new one produced correct results.
The priority was in the wrong place (speed) rather than the business need (correctness).
There's absolutely nothing wrong with making your program fast, so long as it's not to the detriment of correctness or while avoiding making it correct. Fighting for performance boosts in your data access patterns or data layouts while still manipulating the data incorrectly is a fruitless endeavor.
An well-designed API should behave so that you can fudge up whatever is happening behind the scenes, so long as the outputs remain the same based on the inputs. Design for consistency and idempotency. Implementation (read: behind the scenes) details are just that, details, and subject to change. If your implementation is tied to your interface, there are bigger problems and you skipped the Make It Right part.
Most performance has to be intentionally designed in from the beginning if it matters.
So I dove in, technically I felt I could keep the API surface the same. But after about a full month of refactoring it to work with atomic CSS I found many problems. There are just some fundamental limitations to the API design you must enforce to make it work, and without such you really can't merge things properly. It's hard to explain without writing a mini-book, but needless to say the API surface very much can dictate the performance, and if you stuff your API with a bunch of features before making things fast, you may end up like me having to basically start from scratch.
My take: work/right/fast is a loop you must run many times. They also bleed into each other. Sometimes you do work/right and it feels fast, but you haven't deployed it at scale, so you never realize it's not fast. Keep your API as simple as you can, try and hit the fast part somewhat early before you add many features, and don't be afraid to take all your lessons and restart things. If fast is important to your lib, making it right must also be done in tandem with make it fast.
DO IT. DO IT RIGHT. DO IT RIGHT NOW.
I interpreted it as "start by writing a test or some code. make sure the code gives you correct results. only then, when the code generates correct results do you jump in and optimize," which is pretty close to the OP's message.
What this ends up looking like is really:
- write shitty code with the excuse that you could do better, and youll fix it later
- fix it up later by tacking on dirty fixes and removing good code others added to fix specific problem (ignoring chestertons fence)
- then get tired and rewrite it entirely, throwing away all progress. Except for the parts where you just copy paste your old shit because everyone forgot how it works
Sure, there is some inefficiency in re-doing already-working things to improve them, but in my view, less so than in spending more time creating a more perfect thing, but which is often the wrong solution or a solution to the wrong problem altogether.
If it were possible to perfectly know that you are creating the definite right solution to the definite right problem, then sure, go nuts! But in the real world this is essentially never the case, so it is better to first "do it", then if that "it" turns out to be useful, to "do it right", and then since that still inevitably won't actually be "right", to "do it better", and then to "do it better" again and again, until "it" is no longer useful.
Once to understand the problem, once to understand the solution, once to do it properly.
1. Make it possible (even if it's ugly and expensive to do) - Blackberry
2. Make it pleasant/probable (aka improve the UX to customer maximum) - iPhone
3. Make it profitable/cheap (optimize efficiency/cost to deliver) - Android
This implies that the business which did step 3 is more successful than the one that did step 2. It would be interesting to know what Apple and Google think of their businesses relative to each other.
There are two problems that tend to keep much software in what is essentially the "draft" stage, though. One, articulated by many on this thread, is that business incentives really push to "if it's working well enough, it's working well enough." And as some have noted, that's not necessarily a problem! We're, most of us, writing software for pay here, not for fun or personal expression. But! As engineers, we have more insight into if it's really working "well enough" (assuming that we, as engineers, have also taken the time to make sure we understand the product we're building). Things like performance, security, and maintainability are part of making sure it's "good enough," but our non-technical partners and stakeholders can't necessarily see this, and part of our role is to help them see this so that they are making truly informed decisions on if it really is "good enough."
Second, and I feel bad saying this, there's often a dearth of widespread technical ability to actually take code from "ok" to "good." I don't mean this in an elitist way of saying some programmers are just better than others -- I do truly believe that with proper support and mentoring almost anyone who wants to become a better programmer can (see my user name). But I think that as an industry, we actually do a poor job helping our colleagues advance and deepen their skill. The ratio of skilled programmers to new is too small, and of skilled programmers with ability and inclination to level up their junior colleagues even smaller.
That's a decision by business leaders, who by and large have decided that junior-heavy, cheaper dev teams are "good enough."
Chapter 11. Plan to Throw One Away.
It's here if you're interested: https://www.ramijames.com/thoughts/iterate-relentlessly
1. Make it work
2. Make it work well
3. Make it look good
1) The first time, get it done the most expeditious way 2) The second time, do the way you wished you'd done it the first time 3) The third time, automate it...
Make it run, make it right, make it fast (if you have to).
Because I have lived so much of my life generally unable to "Just Start Somewhere", I've given the concept a lot of thought, and a lot of criticism. I can see my bias clearly today, but I'm still not convinced that my criticisms were ever wrong.
--
What's the value in doing something? Is it the doing, or the something?
If the value is in the doing, then there is no value in progress. That's obviously untrue.
If the value is in the something, then where is the doing to make that something in the first place? Clearly, some doing is necessary, too.
I find that the true value of "doing something" lies in the connection between the two. Their interdependence creates structure. By doing, we build something into something more. As a result of the expansion of something, we are better equipped for more doing.
--
But what if something could do itself? To me, this is the ultimate dream of software: the limitless potential of a something that does. The more time I have spent obsessing over this system, the more I have seen the world of software go in the other direction.
The problem lies in our goals. What is it that we desire to do? What is the something that will get us there? These are obvious questions with an obvious answer: application. An application is the kind of something that takes us directly to our desires. There's one problem with that system: every application must be constructed with the same process of doing. There is just enough of a platform for this to work, so everyone who is comfortable with "just doing the thing" can build an application, and be on their merry way.
The platform itself was made with this very category of goal in mind. Our foundations are constrained to a single design pattern: applications. This was not always the case.
--
Once upon a time, we had scripts. Technically, they are still here, but this platform is showing its age. Much like a human's ears, there are some features of the script platform that will never stop growing. New languages. New toolchains. New protocols. The more somethings we build onto script, the more unbalanced the overall platform gets. This is the problem that the application platform avoids.
But how? There are a few valuable weaknesses that application provides:
- Applications are weakly interconnected. If you don't need one, you can simply leave it behind. There is no need to cut it out, because it was never built in.
- Applications are redundant. An application has all of its doing built-in. This allows its UI/UX to be coherent, because it is free to define the doing in its own terms.
- Applications are independent. If an application depends on another application, that dependency is explicit, and can be easily managed. Dependencies can be swapped out with minimal work.
As valuable as each of these are, a weakness is a weakness. They haven't stopped the world of software from reaching incredible goals; but they have been enough to stop me.
--
Is this the end? Is application the final penultimate platform? I'm not convinced. I think we can do better. I think we have everything we need to create a new platform. This new platform can contain the strengths of both script and application. I have a mostly-coherent idea in mind: I call it the story empathizer.
Now I just need to start building it...
It's fine to post workaround URLs in the comments, but please don't make them top-level links.