I have found it valuable to distinguish between the refactoring done in Red-Green-Refactor and the Refactoring done when I have a new story to implement and the design needs to change to accommodate the new feature.
This second form I call Prefactoring.
Prefactoring is performed on otherwise clean well factored code in preparation of a new feature. Prefactoring is perfectly normal on any XP project and in-fact indicates a healthy ongoing design process.
The distinction grew in my mind when we were facing a lot of exiting code debt. I needed a way to distinguish between the 'repair work' I was doing and the 'perfectly acceptable design work'. This was in response to questions like "How much more refactoring is left?" which really meant "How much repair work is left?".
A quick word on Prefactoring and Iterative Design.
Ideally your design applies the OpenClosedPrinciple, which would imply that adding new features would simply require you to add new code. That is great as long as the feature fits one of the axis you have opened your design to change.
However YAGNI indicates you should keep your code as simple as possible. Attempting to open your design to changes in more ways than you currently need can be over-design.
The solution is that you keep your code simple but Prefactor when you need your design to be open in a new dimension. You can then simply add the new feature by adding code. Utopia!
Splitting the work into these two steps makes implementing new features a much simpler process. The new tests are always easy to write. The design always nicely accommodates the the new feature.
As ever, I appreciate Rob for shaming me into finally blogging about this and helping me separate the dumb ideas from the gems.
Nigel Thorne's software development blog, focusing on finding simple solutions to real work problems.
Showing posts with label Design. Show all posts
Showing posts with label Design. Show all posts
Tuesday, February 26, 2008
Thursday, March 08, 2007
...you keep treating it like we are in maintenance mode! [All Development is Maintenance Development]
One of my team said recently "This is a new product. You keep treating it like we are in maintenance mode!". He was right.
Eventually every product gets released. Once it is released you need to be in maintenance mode. Agile development focuses on getting this feedback from running software as soon as possible in by releasing early and often.
As soon as the first release is being used by real people (typically within weeks of starting the project) you are in maintenance mode, whether you like it or not. So all development is done in maintenance mode.
Because of this... You have valuable data you need to migrate with each release. You have users that need to be informed of changes to UI or behavior. You will have to prioritize between bug fixes and new features. You also gain valuable feedback from real users about the usability of your solution.
Here are some rules I have found useful for maintenance development:-
Every developer has their own database instance.
This sandboxes your changes from everyone else's. You wouldn't share the same copy of the code on a shared drive for development, would you?
Every change to the schema is done through scripts.
This allows you to share your db changes with the rest of the team (allowing you to make them more frequently) and handle migration of existing data. Like code, other's don't get your changes until they choose to. You must test these scripts to ensure the data remains intact. I used to have copies of a few big customer databases which I used to verify this. [I'll be releasing a .Net tool to help with this process soon]
Every schema change should have a number.
Every database needs a 'sysinfo' table with one row in it that tells you which version the database is. Every script is numbered in the order they are to be run. Running a script updates the database version number. This makes working out what script to run next simple, allows you to skip steps that don't need running, and unlike scripts that check if a change is needed before doing it, run fast and allow you to put re-do changes you have undone in a previous version.
Stored Procedures are code and should be versioned along with the codebase.
Your process of getting latest should be 1/ get latest. 2/ run the database schema migration scripts on your personal db instance 3/ update any changed stored procedures
Every check in should be atomic.
In other words every check in should contain all code, stored procedure and schema changes to leave you in a state you could get latest, build from scratch, generate a database from the scripts, run all the tests and everything will work.
Have no more than one branch (the version in production) and a trunk (the version in development).
Branches mean duplicated effort. If you release every week, you don't need one at all.
If you work out a good way to seamlessly keep the user trained on the latest version, let me know. I have a feeling the correct solution will involve the app automatically training people on how to user it, which would work for new users too. See Basecamp for an example of this.
Eventually every product gets released. Once it is released you need to be in maintenance mode. Agile development focuses on getting this feedback from running software as soon as possible in by releasing early and often.
As soon as the first release is being used by real people (typically within weeks of starting the project) you are in maintenance mode, whether you like it or not. So all development is done in maintenance mode.
Because of this... You have valuable data you need to migrate with each release. You have users that need to be informed of changes to UI or behavior. You will have to prioritize between bug fixes and new features. You also gain valuable feedback from real users about the usability of your solution.
Here are some rules I have found useful for maintenance development:-
Every developer has their own database instance.
This sandboxes your changes from everyone else's. You wouldn't share the same copy of the code on a shared drive for development, would you?
Every change to the schema is done through scripts.
This allows you to share your db changes with the rest of the team (allowing you to make them more frequently) and handle migration of existing data. Like code, other's don't get your changes until they choose to. You must test these scripts to ensure the data remains intact. I used to have copies of a few big customer databases which I used to verify this. [I'll be releasing a .Net tool to help with this process soon]
Every schema change should have a number.
Every database needs a 'sysinfo' table with one row in it that tells you which version the database is. Every script is numbered in the order they are to be run. Running a script updates the database version number. This makes working out what script to run next simple, allows you to skip steps that don't need running, and unlike scripts that check if a change is needed before doing it, run fast and allow you to put re-do changes you have undone in a previous version.
Stored Procedures are code and should be versioned along with the codebase.
Your process of getting latest should be 1/ get latest. 2/ run the database schema migration scripts on your personal db instance 3/ update any changed stored procedures
Every check in should be atomic.
In other words every check in should contain all code, stored procedure and schema changes to leave you in a state you could get latest, build from scratch, generate a database from the scripts, run all the tests and everything will work.
Have no more than one branch (the version in production) and a trunk (the version in development).
Branches mean duplicated effort. If you release every week, you don't need one at all.
If you work out a good way to seamlessly keep the user trained on the latest version, let me know. I have a feeling the correct solution will involve the app automatically training people on how to user it, which would work for new users too. See Basecamp for an example of this.
Thursday, February 01, 2007
EnABLE your interfaces
Interfaces exist to explain the abilities of a class.
Good: Enumerable (you can enumerate it), Sortable (you can sort it).
Bad: IDrawing, IGeometricObject, ITransaction
Question: IList... good or bad?
Good: Enumerable (you can enumerate it), Sortable (you can sort it).
Bad: IDrawing, IGeometricObject, ITransaction
Question: IList... good or bad?
powered by performancing firefox
Saturday, January 13, 2007
'Where is the MVC Split?' for web apps.. or Client Side Partials
MVC is a great way to apply serperation of concerns to an application's archtecture. Just how far should it go?
(Quick introduction to MVC)
MVC stands for Model, View, Controller. It defines a split in responsibilities between the Model (your representation of the business problem domain), the View of the data and the Controller, which knowns how to orchestrate the various actions and queries you can perform on the data Model.
The Controller works like a dvd player. When it is told to play the dvd player queries the DVD and sends the data to the TV. The TV (being the view) then decides how to present the data so you can see it.
In rails the TV would be the view templates and the bit or rails that knows how to renderthose as HTML, the DVD player would be one of the controller classes, and the DVD is represented as a model class.
The advantage of this design is the seperation of concerns. If you swap your TV for a Cinema overhead projector you don't have to change your DVDs or Player. In the same way, if you decide to render your data as XML, or provide a mobile phone version of your site, you don't have to change your controllers or models. This seperation means the graphic designers are able to experiment with the look and feel of your site without having to get code changes made.
Notice, to control the volume or brightness of the picture, you (being the user) tell the TV, not the dvd player or the DVD. These are view related actions. In rails these would be implemented using javascript (like shrinking and expanding of menus of areas of the screen).
(MVC intro. ends)
I had the following situation: I have a screen full of tree_elements, and a sidebar that lists all root tree_elements. So one is showing a subset of the data the other one is showing. If you create a new root_element, both lists need to be updated.
The sidebar is implemented as a 'partial' that is rendered by the application layout, and hence exists on all my pages. There is a 'quick_add' form in the sidebar to allow you to quickly add new root items. The quick_add form uses ajax and RJS templates to tell the page to add items to the lists.
The problem is that if you are on the screen that lists all items and add a new root item, then there are two lists to update with this item. If you are on another page, then there is only one list to update. As a result the RJS template has to have some conditional javascript logic that says 'update the sidebar list of items, and if the list of all items is on the page, then also update that one'
My concern is this... The RJS for the 'add a new tree item' has to know about all the possible places the tree item will appear, so it can tell the view (whichever one the user happens to be on) to update.
This is wrong! If I add a new screen that represents this list in another way, I would have to extend to RJS for the 'quick_form_create' action to handle yet another special case. The code smell here is 'shot gun changes' [you have to make changes all over the place unrelated to the new added thing]. Really the RJS is sending events to the browser. The page should take that event and decide what needs updating.
I am trying to find a nice way to do it. The problem I have at the moment is when the event causes the page to want to render a new item on the list, the template for it is in the partial (server side). The page could request this as a seperate call, but I want to minimize chatter between the page and the controller. Another solution is for the session to hold onto the current view so the controller knowns what to send, but this again blurs the boundry between view and controller. The controller knows too much. What I'll look into next is having the page hold onto a DOM version of the partial, so it can copy, populate it, and add it to the DOM in the right place. This seems the best solution to me but would need some nice wrapper code in ruby to make it easy to set up.
... [watch this space] ...
the story continues... :)
(Quick introduction to MVC)
MVC stands for Model, View, Controller. It defines a split in responsibilities between the Model (your representation of the business problem domain), the View of the data and the Controller, which knowns how to orchestrate the various actions and queries you can perform on the data Model.
The Controller works like a dvd player. When it is told to play the dvd player queries the DVD and sends the data to the TV. The TV (being the view) then decides how to present the data so you can see it.
In rails the TV would be the view templates and the bit or rails that knows how to renderthose as HTML, the DVD player would be one of the controller classes, and the DVD is represented as a model class.
The advantage of this design is the seperation of concerns. If you swap your TV for a Cinema overhead projector you don't have to change your DVDs or Player. In the same way, if you decide to render your data as XML, or provide a mobile phone version of your site, you don't have to change your controllers or models. This seperation means the graphic designers are able to experiment with the look and feel of your site without having to get code changes made.
Notice, to control the volume or brightness of the picture, you (being the user) tell the TV, not the dvd player or the DVD. These are view related actions. In rails these would be implemented using javascript (like shrinking and expanding of menus of areas of the screen).
(MVC intro. ends)
I had the following situation: I have a screen full of tree_elements, and a sidebar that lists all root tree_elements. So one is showing a subset of the data the other one is showing. If you create a new root_element, both lists need to be updated.
The sidebar is implemented as a 'partial' that is rendered by the application layout, and hence exists on all my pages. There is a 'quick_add' form in the sidebar to allow you to quickly add new root items. The quick_add form uses ajax and RJS templates to tell the page to add items to the lists.
The problem is that if you are on the screen that lists all items and add a new root item, then there are two lists to update with this item. If you are on another page, then there is only one list to update. As a result the RJS template has to have some conditional javascript logic that says 'update the sidebar list of items, and if the list of all items is on the page, then also update that one'
My concern is this... The RJS for the 'add a new tree item' has to know about all the possible places the tree item will appear, so it can tell the view (whichever one the user happens to be on) to update.
This is wrong! If I add a new screen that represents this list in another way, I would have to extend to RJS for the 'quick_form_create' action to handle yet another special case. The code smell here is 'shot gun changes' [you have to make changes all over the place unrelated to the new added thing]. Really the RJS is sending events to the browser. The page should take that event and decide what needs updating.
I am trying to find a nice way to do it. The problem I have at the moment is when the event causes the page to want to render a new item on the list, the template for it is in the partial (server side). The page could request this as a seperate call, but I want to minimize chatter between the page and the controller. Another solution is for the session to hold onto the current view so the controller knowns what to send, but this again blurs the boundry between view and controller. The controller knows too much. What I'll look into next is having the page hold onto a DOM version of the partial, so it can copy, populate it, and add it to the DOM in the right place. This seems the best solution to me but would need some nice wrapper code in ruby to make it easy to set up.
... [watch this space] ...
the story continues... :)
powered by performancing firefox
Wednesday, July 26, 2006
Tuesday, July 25, 2006
Introduction to BDD (Behaviour Driven Development)
BDD is an evolutino of TDD. Those that are doing TDD correctly are aware they are writing in code small specification documents. The code is then written to meet the specification, then the code is checked automatically against the specification using a tool that understands both documents. To call these specifications tests is backwards, as there is nothing to test at the point they are written. More importantly as tests they have an implied scope (unit tests test methods on classes one at a time). If you write specifications instead, then a different scope seem far more appropriate (eg. In context X these things should be true.)
When I first heard about this concept the implementations of frameworks were nothing more than Nunit and Junit with the names changed. Looking at rSpec however things have come along well. Yet again Ruby lends itself well to creating a DSL. In this case for code specification.
Here is an example from rSpec's "RSpec on Rails".
I love it!
Check out Dave Astel's great introduction to BDD.
When I first heard about this concept the implementations of frameworks were nothing more than Nunit and Junit with the names changed. Looking at rSpec however things have come along well. Yet again Ruby lends itself well to creating a DSL. In this case for code specification.
Here is an example from rSpec's "RSpec on Rails".
context "The Person model" do
fixtures :people, :animals
setup do
# fixtures are setup before this
end
specify "should find an existing person" do
person = Person.find(1)
person.should_equal people(:lachie)
person.name.should_equal 'Lachie'
end
specify "should have animals" do
people(:lachie).should_have(2).animals
end
teardown do
# fixtures are torn down after this
end
end
I love it!
Check out Dave Astel's great introduction to BDD.
Subscribe to:
Posts (Atom)