Post by Uncle Buddy on Feb 3, 2021 21:58:36 GMT -8
I'm most of the way finished writing the code that will input new events. All was well until it came to melding with the existing date validation process. The dates module is 2000 lines of very old code that's already been refactored at least twice. By "very old" I mean this was one of the first things I did when I started using Python. I finally got it to work, but it was meant to be used only with a certain type of widget, which I call EntryLabel. This is a Label that displays dates and other data in the events table and a few other places. When you click in it or when it gets focus, it turns into an Entry and you can edit what was there or add data if the Label was empty before.
EntryLabel is a good widget but the problem is that my complex date validation was designed to be used only with this widget. So the dates module is now inflexible code that I will have to hack into in order for it to handle data from other kinds of widgets. This can be done but there are other problems lurking in this ancient code. I'm still a beginner, but not the kind of beginner I was two or three years ago when I wrote this validation procedure, then rewrote it, then changed it to a class, then rewrote it some more...
Truly I believe that it's time to take advantage of my experience as a more advanced beginner and rewrite the code from scratch. The way to write a date validator, I believe today, would be like this:
Why make it a class? Each procedure is working with one value. That value can be passed to the next procedure. A validation procedure is not an object, a noun; it's a verb. A process. The date validator should start with a string input that can come from any kind of widget. Each process that has to be performed on the evolving date string should return a value so that each procedure is called by the next procedure, the procedure that needs that value. One problem with the code I already have is that, since it's a class, it has all these instance variables which--like global variables--can be changed from more than one place. The code gets confusing because you might have to trace through to figure out where something is getting changed.
I avoided classes for a long time, till I learned how to use them, then I overdid it and converted almost everything to a class. No harm was done but some things might have to change. I will have to make a test module and rewrite the code one line at a time so I can test it with any string gotten from any widget that can hold a string value.
The hardest part of the existing date validation code to write was for compound dates such as "from 1885 to 1899" or "between 1789 and 1802". Two dates have to be validated separately, and with all those instance variables bouncing around and certain parts of the code being run twice, it got confusing. This time I will treat every date as if it was a compound date so that the compound date doesn't have to be treated as an exception. Not sure how that'll go but I do want to avoid the confusion of having the exceptions be so complex compared to what I set out to tackle when I first wrote the first version of the validator.
Similar problems are just now cropping up with another edge case, the ambiguous date. Treebard will accept date parts in any order, because my experience with date input on other applications is that it's always annoying and every application has different rules for how to format your input. In Treebard, you can type
I'll bet anything my date validation procedure is a good example of brittle, easily broken, not easily extended, unadaptable spaghetti code that needs to be done over completely. Do I want to spend the next week proving that to myself and get a big headache, or start over now and save myself that week?
The main reason I say this is that secretly bad code (which has been working great for a long time) reveals its tangled nature only when you try to finish something else and the something else can't be finished because the old code isn't adaptable to unexpected interactions. Trying to alter or extend the old code then takes days and ends up becoming a matter of patching this to break that and fixing that to break two other things which then have to be patched. With each improvement being like pulling one of your own teeth. Better to start over, trusting that my current experience will lead me to simpler solutions and it will all be over sooner, with better results, than if I were to spend the next several days banging my head against a giant mountain of molding spaghetti.
EntryLabel is a good widget but the problem is that my complex date validation was designed to be used only with this widget. So the dates module is now inflexible code that I will have to hack into in order for it to handle data from other kinds of widgets. This can be done but there are other problems lurking in this ancient code. I'm still a beginner, but not the kind of beginner I was two or three years ago when I wrote this validation procedure, then rewrote it, then changed it to a class, then rewrote it some more...
Truly I believe that it's time to take advantage of my experience as a more advanced beginner and rewrite the code from scratch. The way to write a date validator, I believe today, would be like this:
Why make it a class? Each procedure is working with one value. That value can be passed to the next procedure. A validation procedure is not an object, a noun; it's a verb. A process. The date validator should start with a string input that can come from any kind of widget. Each process that has to be performed on the evolving date string should return a value so that each procedure is called by the next procedure, the procedure that needs that value. One problem with the code I already have is that, since it's a class, it has all these instance variables which--like global variables--can be changed from more than one place. The code gets confusing because you might have to trace through to figure out where something is getting changed.
I avoided classes for a long time, till I learned how to use them, then I overdid it and converted almost everything to a class. No harm was done but some things might have to change. I will have to make a test module and rewrite the code one line at a time so I can test it with any string gotten from any widget that can hold a string value.
The hardest part of the existing date validation code to write was for compound dates such as "from 1885 to 1899" or "between 1789 and 1802". Two dates have to be validated separately, and with all those instance variables bouncing around and certain parts of the code being run twice, it got confusing. This time I will treat every date as if it was a compound date so that the compound date doesn't have to be treated as an exception. Not sure how that'll go but I do want to avoid the confusion of having the exceptions be so complex compared to what I set out to tackle when I first wrote the first version of the validator.
Similar problems are just now cropping up with another edge case, the ambiguous date. Treebard will accept date parts in any order, because my experience with date input on other applications is that it's always annoying and every application has different rules for how to format your input. In Treebard, you can type
2 14 1810
or 1810 2 14
or 14 1810 2
etc., and Treebard will figure out which one is the day, which one is the year, and which one is the month. This example is obvious but a clarifier will pop up to get more user input in a case like 1810 12 9
. The user will have to tell Treebard which is month and which is day between the two values < 13. Once again the clarifier procedure was working great (aside from being written and patched and fixed and patched) until I tried to apply it in a unique situation. This code is a no-grow. So my new plan is to treat every date as if the clarifier will be needed and then bypass it if it's not needed. Somewhere along the way I heard that edge cases should be handled first, which kinda prevents the scenario of waiting till something goes wrong and then plugging the dam with a spare finger. When you run out of fingers, the code is officially unextendable.I'll bet anything my date validation procedure is a good example of brittle, easily broken, not easily extended, unadaptable spaghetti code that needs to be done over completely. Do I want to spend the next week proving that to myself and get a big headache, or start over now and save myself that week?
The main reason I say this is that secretly bad code (which has been working great for a long time) reveals its tangled nature only when you try to finish something else and the something else can't be finished because the old code isn't adaptable to unexpected interactions. Trying to alter or extend the old code then takes days and ends up becoming a matter of patching this to break that and fixing that to break two other things which then have to be patched. With each improvement being like pulling one of your own teeth. Better to start over, trusting that my current experience will lead me to simpler solutions and it will all be over sooner, with better results, than if I were to spend the next several days banging my head against a giant mountain of molding spaghetti.