Alternative to (or refinement for) State Pattern suffering from LSP violation - oop

I'm having trouble wrapping my head around state-based functionality for an invoicing system we are currently building. The system will support calculation, manual approval, printing, and archiving of invoices.
At first I thought we should use the State Pattern to model this. An invoice would be the context, which delegates printing, archiving, etc. to its currently assigned state.
But this is obviously a bad idea, because the different states (created, approved, printed, archived) should not support the same operations. E.g., you shouldn't be able to print an invoice, which hasn't been approved before. Throwing exceptions for unsupported operations would be a violation of LSP. I found a general description of this problem here.
Does anybody have an idea, how to implement this appropriately?
PS: I'm aware that this might sound like some lame-ass homework assignment, but it's not; I need this for a real world system.

You're basically creating a workflow of application states, where at each state the available operations on an invoice change. The state pattern doesn't seem appropriate, but you can still use it if you also create some operations like boolean canPrint() that would have to be used before calling print(). print() would have a contract that allows throwing exceptions if canPrint() returns false. This way, subclasses wouldn't break that contract. Another option is to have a boolean tryPrint(), that will only print if it can, and return whether it printed.
But, if the states support mostly non-overlapping operations, then maybe the state pattern is not the solution. Take a step back and look for better ways, without trying to fit a specific pattern to your problem. One way is to create a separate class with the necessary operations for each "state": like CreatedInvoice, ApprovedInvoice, etc. These classes would only have the operations they support.

Chain of Responsibility Pattern might help you here.
Adding the how part and fixing the link.
There can be Calculator, Approver, Printer and Archiver classes which are handler classes. These can have processRequest() overridden from a parent abstract class. Invoice can be a class which is passed to each handler's processRequest() method. The advantage with using the pattern here is newer handlers can be added dynamically and chain links with sequence of handlers can be changed easily.

Whether the State Pattern is really appropriate to your situation is not certain, but if it's not, Liskov is not the reason. Throwing some sort of "invalid operation in current state" exception can be defined as possible and valid in the state interface, and then subclasses doing this do not violate LSP.
The classic example used for the State Pattern in the GoF Design Patterns book is a TCPConnection, which definitely has operations not supported or sensible in all states. You can't transmit on a closed connection, for example.

Related

Checking preconditions on parameters in public methods

I'm going to ask your Point of view about a design matter.
The question is basically the following: a public method of an object should always check preconditions in its input parameters or is it better to love responsibility to the caller and "trust the flow" ?
I'm not talking about obvious preconditions such as checking for null to avoid null reference exceptions, but I'm referring to business preconditions in method parameters. This typical happens in DDD Services that perform some kind of validation on input parameters and return an object containing a feedback about that validation.
As an example consider a class CheckPerson having a public method PerformCheck with a single parameter of type Person. Imagine there is a business rule saying that this check doesn't make sense for blonde persons.
In my opinion this check is important and method name should reflect this rule (something like PerformCheckForNonBlondePerson).
Should I add these checks, or should I trust the caller?
Yes you should!
You need to differentiate between input validation and preconditions. Business rules, as you describe them, can be applied in both.
Input validation happens at the system boundary. You expect input validation to fail in some cases. When that happens, you should indicate the error to the client with a useful description of the error.
Preconditions, on the other hand, are part of the contract of a method (or a whole component) somewhere within your system. You always want to be sure this contract is adhered to, because your implementation will probably behave incorrectly otherwise. Here, we use guards to enforce the preconditions. A guard should always pass. If it does not, it is always a programmer error (as opposed to a user error).
#theDmi thanks for sharing your point of view.
I totally agree with your position.
The context when I'm currently working is a team of three people, implementing a large application with a good deal of business logic and domain rules to be taken into account.
The main reason I don't agree with the "trust the flow and delegate responsibility to the caller" philosophy is that this force every developer which is going to make a call to a domain service to explicitly read the code of such a service and to have a good knowledge about the business requirement behind that code.
In my opinion, this is not realistic and furthermore this is an error-prone process.
Domain layer in large application is called by every piece of application logic we are going to write and leaving all the responsibility to the caller is simply too dangerous in my opinion. We don't currently use any kind of library to enforce preconditions check, but I know there are several options out there :)

Concepts of Handling Cases In Different Places

I have a question about the naming of different concepts in object-oriented-programming.
Without trying to explain it through general means, let me illustrate it with two examples of the different concepts I'm speaking of.
I think a good way to illustrate this is the way how to handle damage immunity in games. Let's talk about fire that damages the entities that walk inside of it. Suppose, for example, there are spirits that are immune to fire, so they should not receive damage when walking there.
There are two ways to handle this kind of example situation (actually, three, but one isn't very 'useful'. I will state what it is at the end).
Firstly, the Entity class contains a boolean method/attribute called isImmuneToFire, and the method in the Fire class responsible for handling the process of damaging is checking on that. If this boolean is true, just return the method, if not, call the method damageBy(amount, source) in the entity class.
Secondly, the damage-handling method inside of Fire just calls damageBy(amount, source). Everything regarding immunity is just handled within the individual implementation of the method by the Entity classes. It's more like delegating the actual, repetitive work of immunity-handling to the responsible classes, while giving them more accurate control (for example, some entities could be immune to fire damage for 5 seconds after being hit once, or a player could wear fire immune armor, etc.)
I hope I could illustrate it good enough. Do these two different concepts have a name, or are they too 'marginal' to get one?
The mentioned third concept is to just brute-forcefully check the objects inside the damage-handling method (with instanceof in Java, for example) for their classes and thus deciding on whether damage should be dealt. This of course is a simple approach that just destroys any dynamical aspect and modularity. But if someone has a name for that, I'll accept it of course. Until then, I'll just continue on with calling it the Concept of BFSJ Code, short for Brute-Force Static Jumble Code.
If I'm allowed to tweak your question a little bit I would rather consider this under the light of Double Dispatching. Instead of having the source of damage checking whether it can damage an object, or the object receiving the damageBy(amount, source) message having two switch among all possible values of source, you could get rid of the conditional logic in both places by having Fire send the message fireDamage(amount) instead. That way the source of damage will not have to check whether the object is immune to it or not, and the object will know what to do in its source-specific method.

How do you determine how coarse or fine-grained a 'responsibility' should be when using the single responsibility principle?

In the SRP, a 'responsibility' is usually described as 'a reason to change', so that each class (or object?) should have only one reason someone should have to go in there and change it.
But if you take this to the extreme fine-grain you could say that an object adding two numbers together is a responsibility and a possible reason to change. Therefore the object should contain no other logic, because it would produce another reason for change.
I'm curious if there is anyone out there that has any strategies for 'scoping', the single-responsibility principle that's slightly less objective?
it comes down to the context of what you are modeling. I've done some extensive writing and presenting on the SOLID principles and I specifically address your question in my discussions of Single Responsibility.
The following first appeared in the Jan/Feb 2010 issue of Code Magazine, and is available online at "S.O.L.I.D. Software Development, One Step at a Time"
The Single Responsibility Principle
says that a class should have one, and
only one, reason to change.
This may seem counter-intuitive at
first. Wouldn’t it be easier to say
that a class should only have one
reason to exist? Actually, no-one
reason to exist could very easily be
taken to an extreme that would cause
more harm than good. If you take it to
that extreme and build classes that
have one reason to exist, you may end
up with only one method per class.
This would cause a large sprawl of
classes for even the most simple of
processes, causing the system to be
difficult to understand and difficult
to change.
The reason that a class should have
one reason to change, instead of one
reason to exist, is the business
context in which you are building the
system. Even if two concepts are
logically different, the business
context in which they are needed may
necessitate them becoming one and the
same. The key point of deciding when a
class should change is not based on a
purely logical separation of concepts,
but rather the business’s perception
of the concept. When the business
perception and context has changed,
then you have a reason to change the
class. To understand what
responsibilities a single class should
have, you need to first understand
what concept should be encapsulated by
that class and where you expect the
implementation details of that concept
to change.
Consider an engine in a car, for
example. Do you care about the inner
working of the engine? Do you care
that you have a specific size of
piston, camshaft, fuel injector, etc?
Or, do you only care that the engine
operates as expected when you get in
the car? The answer, of course,
depends entirely on the context in
which you need to use the engine.
If you are a mechanic working in an
auto shop, you probably care about the
inner workings of the engine. You need
to know the specific model, the
various part sizes, and other
specifications of the engine. If you
don’t have this information available,
you likely cannot service the engine
appropriately. However, if you are an
average everyday person that only
needs transportation from point A to
point B, you will likely not need that
level of information. The notion of
the individual pistons, spark plugs,
pulleys, belts, etc., is almost
meaningless to you. You only care that
the car you are driving has an engine
and that it performs correctly.
The engine example drives straight to
the heart of the Single Responsibility
Principle. The contexts of driving the
car vs. servicing the engine provide
two different notions of what should
and should not be a single concept-a
reason for change. In the context of
servicing the engine, every individual
part needs to be separate. You need to
code them as single classes and ensure
they are all up to their individual
specifications. In the context of
driving a car, though, the engine is a
single concept that does not need to
be broken down any further. You would
likely have a single class called
Engine, in this case. In either case,
the context has determined what the
appropriate separation of
responsibilities is.
I tend to think in term of "velocity of change" of the business requirements rather than "reason to change" .
The question is indeed how likely stuffs will change together, not whether they could change or not.
The difference is subtle, but helps me. Let's consider the example on wikipedia about the reporting engine:
if the likelihood that the content and the template of the report change at the same time is high, it can be one component because they are apparently related. (It can also be two)
but if the likelihood that the content change without the template is important, then it must be two components, because they are not related. (Would be dangerous to have one)
But I know that's a personal interpretation of the SRP.
Also, a second technique that I like is: "Describe your class in one sentence". It usually helps me to identify if there is a clear responsibility or not.
I don't see performing a task like adding two numbers together as a responsibility. Responsibilities come in different shapes and sizes but they certainly should be seen as something larger than performing a single function.
To understand this better, it is probably helpful to clearly differentiate between what a class is responsible for and what a method does. A method should "do only one thing" (e.g. add two numbers, though for most purposes '+' is a method that does that already) while a class should present a single clear "responsibility" to it's consumers. It's responsibility is at a much higher level than a method.
A class like Repository has a clear and singular responsibility. It has multiple methods like Save and Load, but a clear responsibility to provide persistence support for Person entities. A class may also co-ordinate and/or abstract the responsibilities of dependent classes, again presenting this as a single responsibility to other consuming classes.
The bottom line is if the application of SRP is leading to single-method classes who's whole purpose seems to be just to wrap the functionality of that method in a class then SRP is not being applied correctly.
A simple rule of thumb I use is that: the level or grainularity of responsibility should match the level or grainularity of the "entity" in question. Obviously the purpose of a method will always be more precise than that of a class, or service, or component.
A good strategiy for evaluating the level of responsibility can be to use an appropriate metaphor. If you can relate what you are doing to something that exists in the real world it can help give you another view of the problem you're trying to solve - including being able to identify appropriate levels of abstraction and responsibility.
#Derick bailey: nice explanation
Some additions: It is totally acceptable that application of SRP is contextual base.
The question still remains: are there any objective ways to define if a given class violates SRP ?
Some design contexts are quite obvious ( like the car example by Derick ) but otherwise contexts in which a class's behaviour has to defined remains fuzzy many-a-times.
For such cases, it might well be helpful if the fuzzy class behaviour is analysed by splitting it's responsibilities into different classes and then measuring the impact of new behavioural and structural relations that has emanated because of the split.
As soon the split is done, the reasons to keep the splitted responsibilities or to back-merge them into single responsibility becomes obvious at once.
I have applied this approach and which has lead good results for me.
But my search to look for 'objective ways of defining a class responsibility' still continues.
I respectful don't agree when Chris Nicola's above says that "a class should presents a single clear "responsibility" to it's consumers
I think SRP is about having a good design inside the class, not class' customers.
To me it's not very clear what a responsability is, and the prove is the number of questions that this concept arises.
"single reason to change"
or
"if the description contains the word
"and" then it needs to be split"
leads to the question: where is the limit? At the end, any class with 2 public methods has 2 reasons to change, isn't it?
For me, the true SRP leads to the Facade pattern, where you have a class that simply delegades the calls to other classes
For example:
class Modem
send()
receive()
Refactors to ==>
class ModemSender
class ModelReceiver
+
class Modem
send() -> ModemSender.send()
receive() -> ModemReceiver.receive()
Opinions are wellcome

Object-oriented programming & transactions

A little intro:
Class contains fields and methods (let me skip properties this time).
Fields represent a state of the class.
Methods describe behavior of the class.
In a well-designed class, a method won't change the class's state if it throws an exception, right? (In other words, whatever happens, class's state shouldn't be corrupted)
Question:
Is there a framework, a design pattern, best practice or a programming language to call a sequence of methods in a transactional style, so that either class's state don't get changed (in case of exception), or everything succeeds?
E.g.:
// the class foo is now in the state S1
foo.MoveToState2();
// it is now (supposed to be) in the state S2
foo.MoveToFinalState();
// it is now (supposed to be) in the state, namely, S3
Surely, an exception might occur both in MoveToState2() and MoveToFinalState(). But from this block of code I want the class foo to be either in the state S1 or S3.
This is a simple scenario with a single class involved, no if's, no while's, no side effects, but I hope the idea is clear.
Take a look at the Memento pattern
The memento pattern is a software design pattern that provides the ability to restore an object to its previous state (undo via rollback).
Not the most efficient method, but you could have an object that represents your transactional data. When you start a transaction, make a copy of the data and perform all operations on that. When the transaction ends successfully, move the copy to your real data - this can be done using pointers, so need not be too inefficient.
Functional programming is a paradigm that seems to fit well to transactional computations. Since no side-effects are allowed without explicit declaration, you have full control of all data flow.
Therefore software transactional memory can be expressed easily in functional terms - See STM for F#
The key idea is the concept of monads. A monad can be used to model an arbitrary computation through two primitives: Return to return a value and Bind to sequence two computations. Using these two, you can model a transactional monad that controls and saves all state in form of continuations.
One could try to model these in an object-oriented way through a State+Memento pattern, but generally, transactions in imperative languages (like the common OO-ones) are much more difficult to implement since you can perform arbitrary side-effects. But of course you can think of an object defining a transaction scope, that saves, validates and restores data as needed, given they expose a suitable interface for this (the patterns I mentioned above).
The simplest and most reliable "pattern" to use here is an immutable data structure.
Instead of writing:
foo.MoveToState2();
foo.MoveToFinalState();
You write:
MyFoo foo2 = foo.MoveToState2();
MyFoo finalFoo = foo2.MoveToFinalState();
And implement the methods accordingly - that is, MoveToState2 does not actually change anything about MyFoo, it creates a new MyFoo that is in state 2. Similarly with the final state.
This is how the string classes in most OO languages work. Many OO languages are also starting to implement (or have already implemented) immutable collections. Once you have the building blocks, it's fairly straightforward to create an entire immutable "entity".
This would be pretty ugly to implement everywhere, but just saving the state locally, then restoring it in the case of an exception would work in simple scenarios. You'd have to catch and rethrow the exception, which may lose some context in some languages. It might be better to wrap it if possible to retain the context.
try {
save state in local variables
move to new state
} catch (innerException) {
restore state from local variables
throw new exception( innerException )
}
When using object copy approach, you have to watch out that the statements to be rolled-back are only affecting the object's or data itself (and aggregates).
But things are getting really difficult if the side-effects of the statements are "more external". For example I/O operations, network calls. You always have to analyze the overall state-changes of your statements.
It gets also really tricky if you touch static data (or evil mutable singletons). Reverting this data isolated is difficult, because other threads could have modified them in between (you could face lost updates).
Reverting/rollback to the past is often not so trivial ;)
I would also consider the saga pattern, you could pass a copy of the objects current state into MoveToState2 and if it throws an exception you could catch that internally and use the copy of the original state to rollback. You would have to do the same with MoveToState3 too. If however the server crashed during a rollback you might still get corrupted state, that's why databases are so good.
Transactional memory fits here the best.
An option could be a transactional storage. Sample implementation you can find here:
http://www.codeproject.com/KB/dotnet/Transactional_Repository.aspx
Memento pattern
Also let me describe a possible pattern on how to implement such behavior:
Define a base class TransactionalEntity. This class contains dictionary of properties.
All your transactional classes inherit from the TransactionalEntity and should operate over some sort of Dependency Properties/Fields, i.e. properties(getters/setters) which store it's values not in local class fields, but in dictionary, which is stored in the base class.
Then you define TransactionContext class. TransactionContext class internally contains a set of dictionaries (one dictionary for each entity that participates in the transaction) and when a transactional entity participates in transaction, it writes all data to the dictionary in the transaction context. Then all you need is basically four methods:
TransactionContext.StartTransaction();
TransactionalEntity.JoinTransaction(TransactionContext context); //if your language/framework supports Thread Static fields, then you do not need this method
TransactionContext.CommitTransaction();
TransactionContext.RollbackTransaction();
To sum up, you need to store state in base class TransactionalEntity and during transaction TransactionalEntity will cooperate with TransactionContext.
I hope, I've explained it well enough.
I think a Command Pattern could be well suited to this problem.
Linky.
I was astonished that no one suggested explicitly the simplest pattern to use .. the State Pattern
In this way you can also eliminate that 'finalState' method and just use 'handle()'.
How do you know which final state is?
The memento pattern is best used with the Command pattern, and usually applies to GUI operations to implement the undo/redo feature.
Fields represent a state of the class
Fields represents the state of the instanced object. You use many times wrong definitions of the OOP terms. Review and correct.

How do you define a Single Responsibility?

I know about "class having a single reason to change". Now, what is that exactly? Are there some smells/signs that could tell that class does not have a single responsibility? Or could the real answer hide in YAGNI and only refactor to a single responsibility the first time your class changes?
The Single Responsibility Principle
There are many obvious cases, e.g. CoffeeAndSoupFactory. Coffee and soup in the same appliance can lead to quite distasteful results. In this example, the appliance might be broken into a HotWaterGenerator and some kind of Stirrer. Then a new CoffeeFactory and SoupFactory can be built from those components and any accidental mixing can be avoided.
Among the more subtle cases, the tension between data access objects (DAOs) and data transfer objects (DTOs) is very common. DAOs talk to the database, DTOs are serializable for transfer between processes and machines. Usually DAOs need a reference to your database framework, therefore they are unusable on your rich clients which neither have the database drivers installed nor have the necessary privileges to access the DB.
Code Smells
The methods in a class start to be grouped by areas of functionality ("these are the Coffee methods and these are the Soup methods").
Implementing many interfaces.
Write a brief, but accurate description of what the class does.
If the description contains the word "and" then it needs to be split.
Well, this principle is to be used with some salt... to avoid class explosion.
A single responsibility does not translate to single method classes. It means a single reason for existence... a service that the object provides for its clients.
A nice way to stay on the road... Use the object as person metaphor... If the object were a person, who would I ask to do this? Assign that responsibility to the corresponding class. However you wouldn't ask the same person to do your manage files, compute salaries, issue paychecks, and verify financial records... Why would you want a single object to do all these? (it's okay if a class takes on multiple responsibilities as long as they are all related and coherent.)
If you employ a CRC card, it's a nice subtle guideline. If you're having trouble getting all the responsibilities of that object on a CRC card, it's probably doing too much... a max of 7 would do as a good marker.
Another code smell from the refactoring book would be HUGE classes. Shotgun surgery would be another... making a change to one area in a class causes bugs in unrelated areas of the same class...
Finding that you are making changes to the same class for unrelated bug-fixes again and again is another indication that the class is doing too much.
A simple and practical method to check single responsibility (not only classes but also method of classes) is the name choice. When you design a class, if you easily find a name for the class that specify exactly what it defines, you're in the right way.
A difficulty to choose a name is near always a symptom of bad design.
the methods in your class should be cohesive...they should work together and make use of the same data structures internally. If you find you have too many methods that don't seem entirely well related, or seem to operate on different things, then quite likely you don't have a good single responsibility.
Often it's hard to initially find responsibilities, and sometimes you need to use the class in several different contexts and then refactor the class into two classes as you start to see the distinctions. Sometimes you find that it's because you are mixing an abstract and concrete concept together. They tend to be harder to see, and, again, use in different contexts will help clarify.
The obvious sign is when your class ends up looking like a Big Ball of Mud, which is really the opposite of SRP (single responsibility principle).
Basically, all the object's services should be focused on carrying out a single responsibility, meaning every time your class changes and adds a service which does not respect that, you know you're "deviating" from the "right" path ;)
The cause is usually due to some quick fixes hastily added to the class to repair some defects. So the reason why you are changing the class is usually the best criteria to detect if you are about to break the SRP.
Martin's Agile Principles, Patterns, and Practices in C# helped me a lot to grasp SRP. He defines SRP as:
A class should have only one reason to change.
So what is driving change?
Martin's answer is:
[...] each responsibility is an axis of change. (p. 116)
and further:
In the context of the SRP, we define a responsibility to be a reason for change. If you can think of more than one motive for changing a class, that class has more than one responsibility (p. 117)
In fact SRP is encapsulating change. If change happens, it should just have a local impact.
Where is YAGNI?
YAGNI can be nicely combined with SRP: When you apply YAGNI, you wait until some change is actually happening. If this happens you should be able to clearly see the responsibilities which are inferred from the reason(s) for change.
This also means that responsibilities can evolve with each new requirement and change. Thinking further SRP and YAGNI will provide you the means to think in flexible designs and architectures.
Perhaps a little more technical than other smells:
If you find you need several "friend" classes or functions, that's usually a good smell of bad SRP - because the required functionality is not actually exposed publically by your class.
If you end up with an excessively "deep" hierarchy (a long list of derived classes until you get to leaf classes) or "broad" hierarchy (many, many classes derived shallowly from a single parent class). It's usually a sign that the parent class does either too much or too little. Doing nothing is the limit of that, and yes, I have seen that in practice, with an "empty" parent class definition just to group together a bunch of unrelated classes in a single hierarchy.
I also find that refactoring to single responsibility is hard. By the time you finally get around to it, the different responsibilities of the class will have become entwined in the client code making it hard to factor one thing out without breaking the other thing. I'd rather err on the side of "too little" than "too much" myself.
Here are some things that help me figure out if my class is violating SRP:
Fill out the XML doc comments on a class. If you use words like if, and, but, except, when, etc., your classes probably is doing too much.
If your class is a domain service, it should have a verb in the name. Many times you have classes like "OrderService", which should probably be broken up into "GetOrderService", "SaveOrderService", "SubmitOrderService", etc.
If you end up with MethodA that uses MemberA and MethodB that uses MemberB and it is not part of some concurrency or versioning scheme, you might be violating SRP.
If you notice that you have a class that just delegates calls to a lot of other classes, you might be stuck in proxy class hell. This is especially true if you end up instantiating the proxy class everywhere when you could just use the specific classes directly. I have seen a lot of this. Think ProgramNameBL and ProgramNameDAL classes as a substitute for using a Repository pattern.
I've also been trying to get my head around the SOLID principles of OOD, specifically the single responsibility principle, aka SRP (as a side note the podcast with Jeff Atwood, Joel Spolsky and "Uncle Bob" is worth a listen). The big question for me is: What problems is SOLID trying to address?
OOP is all about modeling. The main purpose of modeling is to present a problem in a way that allows us to understand it and solve it. Modeling forces us to focus on the important details. At the same time we can use encapsulation to hide the "unimportant" details so that we only have to deal with them when absolutely necessary.
I guess you should ask yourself: What problem is your class trying to solve? Has the important information you need to solve this problem risen to the surface? Are the unimportant details tucked away so that you only have to think about them when absolutely necessary?
Thinking about these things results in programs that are easier to understand, maintain and extend. I think this is at the heart of OOD and the SOLID principles, including SRP.
Another rule of thumb I'd like to throw in is the following:
If you feel the need to either write some sort of cartesian product of cases in your test cases, or if you want to mock certain private methods of the class, Single Responsibility is violated.
I recently had this in the following way:
I had a cetain abstract syntax tree of a coroutine which will be generated into C later. For now, think of the nodes as Sequence, Iteration and Action. Sequence chains two coroutines, Iteration repeats a coroutine until a userdefined condition is true and Action performs a certain userdefined action. Furthermore, it is possible to annotate Actions and Iterations with codeblocks, which define the actions and conditions to evaluate as the coroutine walks ahead.
It was necessary to apply a certain transformation to all of these code blocks (for those interested: I needed to replace the conceptual user variables with actual implementation variables in order to prevent variable clashes. Those who know lisp macros can think of gensym in action :) ). Thus, the simplest thing that would work was a visitor which knows the operation internally and just calls them on the annotated code block of the Action and Iteration on visit and traverses all the syntax tree nodes. However, in this case, I'd have had to duplicate the assertion "transformation is applied" in my testcode for the visitAction-Method and the visitIteration-Method. In other words, I had to check the product test cases of the responsibilities Traversion (== {traverse iteration, traverse action, traverse sequence}) x Transformation (well, codeblock transformed, which blew up into iteration transformed and action transformed). Thus, I was tempted to use powermock to remove the transformation-Method and replace it with some 'return "I was transformed!";'-Stub.
However, according to the rule of thumb, I split the class into a class TreeModifier which contains a NodeModifier-instance, which provides methods modifyIteration, modifySequence, modifyCodeblock and so on. Thus, I could easily test the responsibility of traversing, calling the NodeModifier and reconstructing the tree and test the actual modification of the code blocks separately, thus removing the need for the product tests, because the responsibilities were separated now (into traversing and reconstructing and the concrete modification).
It also is interesting to notice that later on, I could heavily reuse the TreeModifier in various other transformations. :)
If you're finding troubles extending the functionality of the class without being afraid that you might end up breaking something else, or you cannot use class without modifying tons of its options which modify its behavior smells like your class doing too much.
Once I was working with the legacy class which had method "ZipAndClean", which was obviously zipping and cleaning specified folder...