I wrote a binary calculator & binary teaching program in the Rust programming language. I was taking an iterative approach in that I decided to first get a basic "learn binary" game started. This game displays a hex or decimal number to the console and requires the player to enter the number in binary 1s and 0s as a means to help students learn binary.

I then decided to add binary calculator functionality to the program by creating a welcome screen and menu where the user selects between 1. Learn Binary 2. Binary Calculator and 3. Exit.

I then implemented the Binary Calculator functionality.

However, After I did this, I realized that within my Binary Calculator module, a "back to main menu" option was missing - so once a user entered the calculator, he/she would have to exit the program entirely to get to the Learn Binary game and vice versa.

However, in order to implement a "back to menu" feature, I'm realizing that I now have to abstract a loop out into the main function or one function lower, and now each function in succession needs to return some data so that this loop can know when to exit. I'm ending up having to change and add different return types to functions which is having a domino effect and has become more time consuming than expected.

This is just one small example, but I find myself facing this sort of thing often - is this typical in software engineering? Is it normal to have to go back and change a bunch of stuff when new features are added or is it a better idea to think all of this type of thing through ahead of time?

Note that my program is largely procedural but uses a couple OOP constructs as necessary.

  • Possible duplicate of Reducing the ripple effect in my code – gnat Dec 1 at 6:57
  • Imagine your working program as a physical system of rotating and oscillating parts, interconnected by springs, rubber band and solid frames. They all have the freedom to move within their bounds, just as you desired when initially arranging them. The difficulty of moving/changing something depends on the extent and the angle/perspective/axis along which you going to work or look at it. Introducing more flexibility in one direction might require additional helpers and guidelines or change many connected parts. It requires experience to anticipate that but tools like SOLID help you to prepare. – Hero Wanders Dec 3 at 8:01
  • For this particular case, I don't see it as an issue of how you wrote/designed the code. The unanticipated design change and lack of foresight wasn't necessarily coding-related as it was related to unanticipated needs to the user interface. And I don't think that's a small feature change if you expected the program to be able to just work in a sequential A->B->C->Exit fashion without being able to go back and forth and bounce to D then back to A and so on. Whether you are using a modern GUI API or blocking console input, that's a huge change which is often going [...] – Dragon Energy Dec 4 at 4:31
  • [...] to require quite a number of changes in terms of control flow and so forth. So I don't know about the other cases you face with unanticipated design needs, but for this one case any suggestion I'd make to try to reduce the probability of these things happening repeatedly is to kind of work out the user-end design and workflow on a notepad with a ballpoint pen or something before you even start coding it. That doesn't mean to work out everything but you might at least realize that you need to be able to go back and forth in the UI here upfront. – Dragon Energy Dec 4 at 4:33
  • This is something I do see a lot in my field is that programmers can spend a lot of time upfront or in hindsight because of massive blindspots in terms of user expectations. That even includes profiling and optimization. I've seen developers spend countless hours profiling and optimizing some benchmark and test case which isn't at all representative of how the users use the software which actually pessimized the common use cases in favor of optimizing the rare ones (and that was even with a profiler pointing out hotspots, but against a test case which wasn't very real-world)... – Dragon Energy Dec 4 at 4:38
up vote 7 down vote accepted

Yes, this is normal.

The conventional wisdom these days is that it is overall more efficient to build what you need first, without first considering all consequences on all possible later features or requirements. This means that you are willing to revise some design decisions you made earlier (and you are comfortable in making such changes without fear of regression because your functionality is semi-automatically verified by an extensive test suite).

Thinking about the global design of all modules first would probably have saved you this detour, but thinking about problems in advance turns out to be surprisingly hard in general - usually it is easier to find out what you need at point X if you've already progressed to point X-1. Therefore, there is a trade-off between the cost of planning ahead (spending time on considering many alternatives, most of which never get built) and the cost of plunging forward (requiring additional work to change design decisions that would have been cheaper to fix earlier). You've probably heard the words "agile" and "waterfall". That's exactly what this trade-off is about.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.