6 ms·
"Recommendation 2: Include Only What You Need" The slide refers to the inversion of control principle but can easily include other important aspects of includi
by Dowwie 8y ago
"Recommendation 2: Include Only What You Need"
The slide refers to the inversion of control principle but can easily include other important aspects of including only what is needed.
I would like to expand on this for discussion. Consider the challenges of not over-engineering solutions to problems you and others don't fully understand, yet. Unless you work for NASA, you won't fully know what you need until you need it.
How do programmers here account for the unexpected?
- AlexanderDhoore 8y agoYou don't because you can't. It is impossible to predict the future so please stop trying. Just implement what you need today and do the rest later. "Always implement things when you actually need them, never when you just foresee that you need them" https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it EDIT: The way I think about this is that software development has a very large degree of unknown unknowns. More than maybe other domains like architecture/chemistry/...
- TotempaaltJ 8y ago> Just implement what you need today and do the rest later. I'd add that, while you shouldn't change the complexity of your implementation very much, you should look at potential future scenarios and migration paths. Sometimes you can make small changes to the plan that make migration paths easier. Optimize for ease of change I suppose. Obviously the effort you put into this should be proportional to the complexity/importance of the problem.
- koolba 8y ago> Sometimes you can make small changes to the plan that make migration paths easier. Optimize for ease of change I suppose. This works fine for known future changes, say if you’re implementing X, and know that a similar Y and Z are down the road. Beyond that it leads to the usual problems of crystal ball based planning.
- vincnetas 8y agoAnd here comes the part where experience plays its role. History tends to repeat itself, so if you been/seen certain situations you can account for high possibility of them happening again.
- menzoic 8y agoHow does NASA fully know what they need? I would think they have the most unknowns out of any other engineering organization.
- marcosdumay 8y agoThey mostly don't get to take their equipment back to update it. So they better know very well what they need. (Yes, there's some amount of remote update, they still can't move fast and break things.) As usual, in engineering, needs create capabilities. It is very expensive and risky to go fully determining your needs before execution, but they pay for it.
- eps 8y agoListen to the user feedback and _selectively_ act on that. Not all feedback is good, not all of it is applicable, requests for marginal features that benefit only few are exceedingly common. All feedback should be taken strictly in advisory capacity and assessed critically. However if you did miss something useful or dearly needed, it will surface almost immediately. We've been practicing this for ages and it works extremely well.
- scarygliders 8y ago> How do programmers here account for the unexpected? You don't. At least, I don't. When I'm writing code for an application, I'm doing the following... "Hmmm, I need a function to perform <certain thing>" Function is written... tested... debugged until <certain thing> is achieved. Job done. Whilst writing said code, I do not think to myself "Hmmm... y'know in the future it might need to also do <some future thing>" and proceed to add additional function parameters and write additional code which would only be useful sometime in the future, just in case. No. I write sufficient code for what is required of said function at that moment in time. It is only if and when required would I then add any additional parameters and code to that function. Or write new functions.
- klausjensen 8y agoWhen I started as a developer 20 years ago, this was the most difficult thing for me. I would tend to over-think and include WAY too many "what if"-scenarios. So that is what I try to teach junior developers today: Only write what is required now and don't think too much about what the function might be expanded to do in the future.
- pytester 8y ago>"Hmmm... y'know in the future it might need to also do <some future thing>" Those are my trigger words. My experience is that about 97% of the time somebody says those words (in the past it's been me) in the context of writing software and it turns out that: * <some future thing> is never required. * <some future thing> is required but it ends up being needed in a completely different form, rendering the preparation work pointless. * <some future thing> was nice to have but it ended up so far down the list of priorities that it might as well not have been. This applies to every level of the stack from one off functions to grand features, to refactoring, testing and even to things that many people consider "best practice". I don't think it pays to be an extremist about many things in software but "if there isn't a glaring need for it then don't implement it" is one of them.
- javajosh 8y agoThere's a difference between not adding bells and whistles you might not need, and shipping asymmetric, broken abstractions. Just because your app doesn't need to support vectors in the negative plane, for example doesn't mean you should ship a vector library that doesn't support negative numbers. In the same way I see well-meaning devs "dribble" data into an API, forcing future users to expand the API into a shape that could easily have been anticipated, and made cohesive sense. This stinginess with API is particularly bad because now developers learn to not respect API boundaries at all, because there aren't any. (And additionally it contributes to a lot of unnecessary indirection and typing because you have to define subset types at both ends of the API.) So, yeah, DON'T just add arbitrary stuff because you'll think it will be useful to someone; but DO add stuff to maintain the symmetry and understandable abstraction of what you've made.
- nurettin 8y ago>> How do programmers here account for the unexpected? I work on systems that need to run reliably. However, they depend on data collectors (like sensor data or web scraping) that are not known for their reliability or scalability. We do lots of retries, log errors and failures, and patch problems until things work as expected. One thing that helps is the use of sentry.io . It alerts us about exceptions and detects regressions/regression fixes by checking if there were any commits that might have caused or fixed issues.
- entity345 8y ago> How do programmers here account for the unexpected? This is where good architecture and design come into play. Design for what you know and need now but use good principles (OO, etc.) so that code can be modified in a sane way.
- ummonk 8y agoImplement what is needed now while making sure that your code is simple and easy to modify, extend, and refactor.
- karmakaze 8y agoI think most experienced devs here are talking about one side or the other of balancing benefits/costs. Yes, there are pros/cons of taking it further one way or the other. The best way I've been able to prioritize is to the the current code primarily serve current needs. If there are other likely and soon expected capability, make some accomodations that don't negatively impact the complexity of serving the current function. If they're at odds, merely document the ideas to handle the expanded case. The situation to avoid is to pay a complexity tech debt now, for something that may not occur for some time, possibly never with all the maintenance of current features upon that complexity. A common reoccurrence is generalized methods. There was a PATCH endpoint for main entity which I'm sure started out innocently enough with maybe just two change sets. Following the intents through the layers of this choke point implementation is unpleasant. We could achieve the same by composing variants at a higher level so that each concern is separated from the others, but then we introduce this 'machinery' that may not be warranted. If there are many or a dynamic components then it may be the best solution but not until. I recently fell for this myself. On recognizing that a particular service was just a combination of two state machines, I abstracted the state machine operation and applied it to each subproblem. It worked like I expected but the result wasn't right. The state machine machinery was more visible than the core logic. I eliminated the concrete abstraction and created two implicit state machines that invisibly did what was required for each subproblem. If we already had a common state machine form that we were familiar with, things could be different but not when introducing it into a codebase for the first time.