[Tutor] How to refactor a simple, straightforward script into a "proper" program?
David L Neil
PyTutor at DancesWithMice.info
Mon Jan 6 23:31:06 EST 2020
On 7/01/20 12:29 AM, Alan Gauld via Tutor wrote:
> On 06/01/2020 03:25, boB Stepp wrote:
>
>> So I have been thinking a lot about this today and find myself
>> stumbling around in a confused daze despite making lists, crude
>> UML-like diagrams, etc. So questions!
>
> OK, This switches the emphasis of the thread but lets go...
Maybe, but doesn't *some* of the discussion relate to design decisions?
>> I think the basic unit of code organization would be a ReadingMaterial
>> class, choosing this name to reflect Alan's thoughts that ultimately
>> there might be other things to read besides paper-based books.
>
> Good thinking. But...
>
> I'd create a very thin abstract class with just the interface
> - remember think about behaviour first not attributes.
> Attributes are only there to support behaviour.
>
> Then forget about eReaders etc for now and create a subclass
> that deals with the concrete problem of a paper book.
>
>
>> keep with the current confines of the original problem as stated, an
>> object of this class would have the following user-entered attributes:
>> title, total_amount_to_read, total_amount_read, and goal_date. I
>> switched from "pages" to "amount" as my best wording to reflect a
>> potential shift from pages read to percent of item read or lines read
>> or whatever. This means that I will have to throw in the concept of
>> "units" if I do this generalization now.
>
> The units are specific to te subclass. Amount are the generalized concept.
>
> My only question is whether the dates are relevant to the book? Or do
> you need a Reader object? It is the reader who has reading goals. The
> book will tell you how much to read and current position. But it is not
> interested in dates.
Not necessarily. The reader doesn't know if (s)he is about to drop dead!
Alternately, if the book has been borrowed (eg library), then it has a
finite availability.
> So now we have two objects interacting. And in theory you could have
> multiple readers reading the same book, and one reader reading multiple
> books.
>
>> I know the Agile people
>> might say stick with today's problem (pages) and worry about other
>> units when one is forced to. So I may stick with pages after I hash
>> out more important difficulties. So back to "pages" for now.
>
> Correct approach. Recognize that you may have another type of
> ReadingMaterial to deal with in the future, but park it for
> now - its a differnt class.
+1
Make it work before you make it better!
>> First point of confusion: the creation of the ReadingMaterial object.
>> Should it start with (a) my_book = ReadingMaterial() or with (b)
>> my_book = Reading_Material(title [, total_pages_to_read,
>> total_pages_read, goal_date])? The brackets indicate optionally
>> starting with all four attributes from the get-go. In other words in
>> (a) the object would see to initiating the acquisition of user input
>> itself, while the second has some other entity taking care of user
>> input and then passing it into the instantiation process.
>
> Separate user interaction from logic. What happens when you want to use
> this ReadingMaterial object in a GUI? So you have a ReadingMaterialView
> that can deal with interacting with the user to create the book. In an
> industrial version of this we probably have a database of readMaterial
> and the readers select an existing book. The creation of the book is a
> database(library?) admins job.
>
> So I'd definitely opt for a separate data collection function/object
> and then instantiate the object with the data already gathered.
+1, which aligns with earlier mention of MVC
Once again, keeping in-mind the future possibility of using a GUI, first
write the code to work from the terminal-only.
>> the proper way to proceed? On the (a) side, ReadingMaterial knows
>> what it needs and it is the natural location for future additional
>> attributes that may need to be acquired someday.
>
> It knows what it needs but it does that by being created with it. Thats
> what __init__() - ie. initialization - is for.
>
>> direction I am currently leaning. So the initialization of a
>> ReadingMaterial object might look like:
>>
>> class ReadingMaterial:
>> def __init__(self):
>> self.title = _get_input(???)
>> self.total_pages_to_read = _get_input(???)
>> self.total_pages_read = _get_input(???)
>> self.goal_date = _get_input(???)
>
> Again, how does that work in a GUI? Or on the web?
Alternate view: Were the get_input() coded as part of ReadingMaterial,
how would we be able to re-use the method when needing to input into
some other class, on some other project, some other day, ...
> I am answering your issues as I go and in each case you have
> already guessed the response. I think thats a good thing! :-)
+1
> Now start writing some usecases. Forget about code for now.
> How does the user interact with this application?
> That should start to give you clues as to what methods
> the classes need to support.
...
> It is really important to have it clear in your head how
> this app will work as a dialog with the user. That is fundamental to
> understanding what operations it needs to support. And operations
> translate to methods. And then you decide which object supports
> which operations. That in turn will tell you which attributes are
> needed in which class.
+1
--
Regards =dn
More information about the Tutor
mailing list