Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Approaching refactoring

I have a very data-centric application, written in Python / PyQt. I'm planning to do some refactoring to really separate the UI from the core, mainly because there aren't any real tests in place yet, and that clearly has to change.

There is some separation already, and I think I've done quite a few things the right way, but it's far from perfect. Two examples, to show you what kind of things are bothering me:

  • When the user right-clicks on the representation of a data object, the context menu that pops up is created by the data object, although this data object (essentially the ORM representation of a database row) should clearly have nothing to do with the UI.

  • When something is written to the database, but the write fails (e.g. because the database record is locked by a different user), the classical "retry / abort" message box is presented to the user. This dialog is created by the data provider*, although the provider should obviously not have any UI functionality. Clearly, the provider can instead raise an exception or otherwise indicate failure, and the UI can catch that and act accordingly.

    * that's the word I use for the object that basically represents a database table and mediates between its data objects and the database engine; I'm not sure whether that's what is usually called a "provider"

I don't have experience with testing, so I don't easily "feel" testability problems or the like, but before I get into that, some reorganizing has to be done.

There is no complicated business logic involved (it's mainly just CRUD, yes, even without the D), and this would be much more reorganizing than rewriting, so I'm not really concerned about introducing regression bugs like discussed in this question.

My plan is to start refactoring with the idea in mind that the UI part could easily be ripped out to be replaced by, say, a web frontend or a text-based interface instead of the Qt interface. On the other hand, Qt itself would still be used by the core, because the signal/slot mechanism is used in quite a few places, e.g. data objects emit a changed signal to indicate, well, you know what.

So, my question: Is that a feasible approach to increase testability and maintainability? Any other remarks, especially with Python in mind?

like image 293
balpha Avatar asked Jan 17 '10 16:01

balpha


People also ask

What is the refactoring process?

Refactoring is the process of changing a software system so the software's structure and performance are improved without altering the functional behavior of the code. Refactoring is used to improve system maintainability and extend its usable life span.

What is an example of refactoring?

Examples are: adding, removing, and introducing new parameters, replacing the parameter with the explicit method and method call, parameterize method, making a separate query from modifier, preserve the whole object, remove setting method, etc.

What is the refactoring in testing?

Refactoring or Code Refactoring is defined as systematic process of improving existing computer code, without adding new functionality or changing external behaviour of the code. It is intended to change the implementation, definition, structure of code without changing functionality of software.


2 Answers

If you have not done so already, read "Working Effectively with Legacy Code" by Michael Feathers - it deals with exactly this sort of situation, and offers a wealth of techniques for dealing with it.

One key point he makes is to try and get some tests in place before refactoring. Since it is not suitable for unit tests, try to get some end-to-end tests in place. I believe that Qt has its own testing framework for driving the GUI, so add tests that manipulate the GUI against a known database and verifies the result. As you clean up the code you can replace or augment the end-to-end tests with unit tests.

like image 166
Dave Kirby Avatar answered Oct 16 '22 12:10

Dave Kirby


If you want to extract all GUI parts of your application from all the other parts in order to tests all your application, you should use the Model-View-Presenter: You can find some explanation here and here.

With this model, all your services of your application uses the presenters whereas only the user can interact directly with the views (GUI parts). The presenters are managing the views from the application. You will have a GUI part independent from your application in the case you want to modify the GUI framework. The only thing you will have to modify are the presenters and the views themselves.

For the GUI tests you want, you just have to write unit tests for presenters. If you want to test GUI uses, you need to create integration tests.

Hope that helps!

like image 33
Patrice Bernassola Avatar answered Oct 16 '22 11:10

Patrice Bernassola