Lets say that I have a message queue which receives messages which have the members name, type and so on.
Is there a name for a type of observer on this queue which expects a message with a certain content?
if (message.name.equals(observer.wantedName) {
observer.notify();
}
The following is just an example in pseudo code how to solve the problem. The MessageQueue has a hashtable which keys are the message types and values arrays with listeners for this message type. Also you'll need an additional argument to YourMessageQueue:observe() that describes the condition.
class YourMessageQueue extends /* or implements */ EventDispatcher {
function addMsg(msg) {
foreach(this.listeners[msg.type] as listener) {
listener.notify(msg, this);
}
}
}
class YourObserver implements Observer {
function createMesssageQueue() {
msgq = new MessageQueue();
msgq.addObserver(this, 'foo');
}
}
class EventDispatcher {
protected hashtable observers;
function addObserver(Observer observer, string eventType) {
this.observers[eventType].push(observer);
}
}
interface Observer {
function notify($data, $sender);
}
Related
I am trying to solve a design problem with design patterns. Now that I have the basics I am fairly sure that I overcomplicated it a lot. I seem to have multiple empty interfaces, and I probably could do with less with a different design. Also I'm not sure if future developers on the project will have an easy time figuring out this tangle.
I've made a mockup of the structure of the classes. The example is dumbed down to two service types (cf BaseAnimalService extensions), in the project there are more. There are also more BaseStrategy implementations.
At first I want do differentiate between a context for a CatService or DogService. This is done using a Map in the BaseStrategy class, which has the BaseAnimalService as value to enable polymorphism between the Cat/DogService. Based on the generic type of the BaseStrategy, implemented in the Dog/CatStrategy a different configurationMap is used, which in turn, based on the type of the criteria, loads one or the other implementation of the Dog/CatService.
The configuration maps are defined in the spring.xml file.
Since the Dog/CatService both implement an extra interface, cf. SomeOtherCat/DogService, which is external to my design, the Dog/CatService both have have empty interfaces too. SomeOtherCatService and SomeOtherDogService aren't related and aren't editable so I can't use them polymorphically, which is the reason for the Base/Cat/DogService interfaces.
I thought about making the BaseStrategy a StrategyFactory which returns a Cat/DogStrategy which in turn checks the type of the criteria for which BaseAnimalService to use. But since both these strategies use the same logic for their strategies, this would mean I would have to create another base class.
What do you think? Any suggestions on what would be a better design for this problem? Or any improvements to the current one?
class BaseStrategy<T extends BaseAnimalService> {
private ContextService contextService;
private Map<String, BaseAnimalService> configurationMap;
T getService() {
return configurationMap.get(contextService.getCurrentContext());
}
}
interface BaseAnimalService {
//empty
}
interface DogService extends BaseAnimalService {
//empty
}
interface CatService extends BaseAnimalService {
//empty
}
class DogStrategy extends BaseStrategy<DogService> {
//empty
}
class CatStrategy extends BaseStrategy<CatService> {
//empty
}
class BritishShortHairServiceImpl implements CatService, SomeOtherCatService {
#Override //source: SomeOtherCatService, same for other implementations below
void pur() {
//pur
}
}
class LionServiceImpl implements CatService, SomeOtherCatService {
#Override
void pur() {
//pur
}
}
class PitBullServiceImpl implements DogService, SomeOtherDogService {
#Override
void wagTail() {
//wag tail
}
}
class ChihuahuaServiceImpl implements DogService, SomeOtherDogService {
#Override
void wagTail() {
//wag tail
}
}
class CatPerson {
private BaseStrategy<CatService> catStrategy;
void pet() {
catStrategy.getService().pur();
}
}
class DogPerson {
private BaseStrategy<DogService> dogStrategy;
void feed() {
dogStrategy.getService().wagTail();
}
}
Relevant spring.xml snippet:
<bean id="baseStrategy" abstract="true"
class="com.animals.services.BaseStrategy">
<property name="contextService" ref="contextService"/>
</bean>
<bean id="catServiceStrategy"
class="com.animals.services.CatStrategyImpl"
parent="baseStrategy">
<property name="strategyConfigurationMap">
<map>
<entry key="CONTEXT1" value-ref="britishShortHairService"/>
<entry key="CONTEXT2" value-ref="lionService"/>
</map>
</property>
</bean>
<bean id="dogServiceStrategy"
class="com.animals.services.DogStrategyImpl"
parent="baseStrategy">
<property name="strategyConfigurationMap">
<map>
<entry key="CONTEXT1" value-ref="pitbullService"/>
<entry key="CONTEXT2" value-ref="chihuahuaService"/>
</map>
</property>
</bean>
I am not familiar with Spring or its Context Service model, so I am approaching this question from a general, language-independent OOP perspective.
In my opinion you need to be thinking about ways that you can pass configurations through the constructor (dependency injection) rather than switching based on maps. You need more "has a" relationships (composition) and less "is a" relationships (inheritance).
An AnimalService can take an animal object as an argument to the constructor. We can say that an AnimalFeedbackBehavior must include methods for positiveFeedback(), neutralFeedback(), and negativeFeedback() -- but how those methods are implemented can vary from animal to animal. A Cat would purr() in response to a positive interaction but a Dog would wagTail().
An AnimalOwner can feed() any animal and trigger AnimalFeedbackBehavior.positiveFeedback(). The AnimalOwner does not need to know what that behavior does behind the scenes. It does not even need to know what species of animal it has. All it needs to know is that this method exists.
interface AnimalFeedbackBehavior {
positiveFeedback(): void;
neutralFeedback(): void;
negativeFeedback(): void;
}
class AnimalOwner {
private animal: AnimalFeedbackBehavior;
// pass animal instance to the constructor
constructor( animal: AnimalFeedbackBehavior) {
this.animal = animal;
}
// trigger positive feedback when feeding
feed() {
this.animal.positiveFeedback();
}
}
class Cat implements AnimalFeedbackBehavior {
purr() {
//do something
}
positiveFeedback() {
this.purr();
}
/* ... rest of class ... */
}
Typescript Playground Link
Here we assumed that feed is always a positive interaction. But what if we want different animals to have different reactions to the same interactions? chase() might be positive for a Dog but negative for a Cat. A naïve approach would be to switch the feedback based on a map. But an ideal design allows for maximum abstraction where the AnimalOwner doesn't need to know anything about the animal types.
Let's try a totally different setup.
If you are dealing with a small set of behaviors, we could require that the animal has a response for each behavior, rather than positive/neutral/negative.
interface AnimalBehavior {
feedResponse(): void;
chaseResponse(): void;
}
But this could get unwieldy quickly. We could define an animal with a respond method that responds to some sort of generic action object. In the implementation, it can do something in response to the action or just ignore it.
This setup also makes the composition of multiple overriding behaviors more intuitive since we can go through a chain of respond functions until one handles it. We want to know it there was a response or not so we need to return something from the response function. If it's basically void then we can return a boolean flag that's true if it responded. If a response should return a value than you would return either that value or undefined.
interface Action {
type: string;
}
// we may want to attach some sort of data
interface ActionWithData<T> extends Action {
type: string;
data: T;
}
interface AnimalBehavior {
respond( action: Action ): string | undefined;
}
class Animal implements AnimalBehavior {
// an animal has an array of behavior responders
// as written, the earlier behaviors in the array override later ones
private behaviors: AnimalBehavior[];
// can instantiate an animal with multiple behaviors
constructor( behaviors: AnimalBehavior[] = [] ) {
this.behaviors = behaviors;
}
// can also add behaviors after the fact
public addOverride( behavior: AnimalBehavior ) {
this.behaviors = [behavior, ...this.behaviors];
}
// loop through behaviors until one responds
public respond (action: Action): string | undefined {
for ( let element of this.behaviors ) {
// could be a response or might be undefined
const response = element.respond(action);
if ( response ) {
return response;
}
}
// could do something here if no behaviors responded
return undefined;
}
}
class AnimalOwner {
private animal: AnimalBehavior;
// pass animal instance to the constructor
constructor( animal: AnimalBehavior) {
this.animal = animal;
}
// animal can respond to the feed action, or not
feed(): string | undefined {
return this.animal.respond({type: 'feed'});
}
chase(): string | undefined {
return this.animal.respond({ type: 'chase' });
}
}
These implementations feel sloppy at the moment. Right now none of them use this so it's pointless to use a class. But just to give you an idea:
class DogBehavior implements AnimalBehavior {
respond(action: Action): string | undefined {
switch (action.type) {
case 'feed':
return "Wag Tail";
case 'chase':
return "Run Around";
default:
return undefined;
}
}
}
class PuppyBehavior implements AnimalBehavior {
respond(action: Action): string | undefined {
switch (action.type) {
case 'feed':
return "Jump";
default:
return undefined;
}
}
}
class ChihuahuaBehavior implements AnimalBehavior {
respond(action: Action): string | undefined {
switch (action.type) {
case 'feed':
return "Yip";
default:
return undefined;
}
}
}
Both the Animal composition and the individual behaviors implement AnimalBehavior, so an AnimalOwner can take a DogBehavior directly or it can take an Animal composed of a DogBehavior and some other behaviors.
const owner1 = new AnimalOwner(new DogBehavior());
let res = owner1.feed(); // is "Wag Tail"
The order matters. If we have a chihuahua puppy, we need to decide whether ChihuahuaBehavior overrides PuppyBehavior or vice-versa.
// prioritizes puppy
const owner2 = new AnimalOwner(new Animal([new PuppyBehavior(), new ChihuahuaBehavior(), new DogBehavior()]));
res = owner2.feed(); // is "Jump" from PuppyBehavior
res = owner2.chase(); // is "Run Around" from DogBehavior because not overwritten
// prioritizes chihuahua
const owner3 = new AnimalOwner(new Animal([new ChihuahuaBehavior(), new PuppyBehavior(), new DogBehavior()]));
res = owner3.feed(); // is "Yip" from ChihuahuaBehavior
Typescript Playground Link
I just noticed that some of my listeners do not use the queue I expected them to use. Our team upgraded from Laravel 5.2 to 5.5 a few weeks back, and I guess this is when the problem started happening. There hasn't been much load on the system, so I only discovered it by accident.
Anyway. I used to set the queue name on the listener through a queue method, like so:
public function queue(QueueManager $handler, $method, $arguments): void
{
$handler->connection()->push($method, $arguments, Queue::getNotificationQueue());
}
This approach is not working anymore, so a default queue ends up handling the job instead of the expected notification queue.
So I looked at the documentation https://laravel.com/docs/5.5/events#queued-event-listeners, which states that the name should be set on a queue property on the listener. My problem is that I have the queue name in an environment variable, so I cannot just set it directly as a property, as shown in the documentation and it does not work to set it on the constructor, like so:
protected $queue;
public function __construct()
{
$this->queue = Queue::getNotificationQueue();
}
Does anyone here have an idea of how I can get around this?
Specifically for SQS queues the $queue property acts a bit weird because it doesn't seem to refer to queues defined in queue.php, but it expects a full queue url, so even the example in the documentation seems off.
But for dynamic queue names on queued event listeners that for example changes depending on environment, making a custom SqsConnector and SqsQueue will be one way to solve your issue.
Here is an example of implementation.
ACMEEventListener.php
class ACMEEventListener implements ShouldQueue
{
public function handle(Event $event): void
{
// I'm going to a custom queue
}
public static function getQueue(): string
{
return 'https://sqs.eu-central-1.amazonaws.com/<account id>/<queue name>';
}
}
CustomSqsConnector.php
use Illuminate\Queue\Connectors\SqsConnector;
use Aws\Sqs\SqsClient;
class CustomSqsConnector extends SqsConnector
{
public function connect(array $config)
{
$sqs = new SqsClient($config);
return new CustomSqsQueue($sqs, $config['queue']);
}
}
CustomSqsQueue.php
class CustomSqsQueue extends \Illuminate\Queue\SqsQueue
{
public function push($job, $data = '', $queue = null)
{
if ($job instanceof CallQueuedListener && method_exists($job->class, 'getQueue')) {
$queue = $job->class::getQueue();
}
return $this->pushRaw($this->createPayload($job, $data), $queue);
}
}
CustomSqsQueueServiceProvider.php
class CustomSqsQueueServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->booted(function () {
$this->app['queue']->extend('custom_sqs', function () {
return new CustomSqsConnector;
});
});
}
}
And then in your queue.php, your default SQS connection driver from sqs to custom_sqs
In my DDD project I'm trying to implement the state pattern with java enum.
I have a problem when validating entity methods that have behaviour depending on the state.
For validating I use the notification pattern.
I follow the "always valid entity" approach, so that in every operation I first call a "isValidForOperation" validation method.
Here's the code, just the relevant for simplicity:
The entity:
public class Task extends AggregateRoot<TaskId> {
...
private State state;
...
// Operation with behaviour depending on the state
// It's a transition from "ASSIGNED" state to "IN_PROGRESS" state
// I apply the state pattern here
public void start () {
State next = this.state.start ( this );
this.setState ( next );
}
...
}
The java enum modeling the state:
public enum State {
ASSIGNED {
public State start ( Task task ) {
// Validation method to ensure the operation can be done
assertTaskIsValidForStart ( task );
// Business logic
...
// Return the next state
return ( State.IN_PROGRESS );
}
}
...
// more enum values for other states
...
// Default implementation of "start" operation
// It will be executed when the current state is not "ASSIGNED"
// So an error would be generated
public State start ( Task task ) {
// I can't apply notification pattern here !!!
// I would have to throw an exception
}
}
The validation method follows the notification pattern.
It collects all possible errors in a notification object.
This notification object is passed to an exception.
The exception is thrown and then the application layer catches it and return all the error messages to the client.
public void assertTaskIsValidForStart ( Task task ) {
Notification notification = new Notification();
if ( errorCondition (task) ) {
notification.addError(...);
}
...
// more errors
...
if ( notification.hasErrors() ) {
throw new TaskNotValidForStartException ( notification.errors() );
}
}
How could be the notification pattern applied (in conjuntion with the state pattern) when the error condition is about the invalid transitions between states?
Any ideas?
UPDATE:
I found a solution. I put the whole operation that depends on the state in the entity, and apply the state pattern more fine-grained, just to the code needed. This way I apply the pattern to calculate just the next state, so that I can check if the transition is allowed and apply the notification pattern too.
Code:
public class Task extends AggregateRoot<TaskId> {
...
private State state;
...
// Operation with behaviour depending on the state
// It's a transition from "ASSIGNED" state to "IN_PROGRESS" state
// I apply fine-grained state pattern here
public void start () {
// Validation method to ensure the operation can be done
// One of the validations will be if the transition is allowed
assertTaskIsValidForStart ( this );
// Business logic
// If it depends on the state, I would apply state pattern delegating to another method
...
// Set the next state
State next = this.nextStateForStart();
this.setState ( next );
}
...
public State currentState() {
return this.state;
}
...
public State nextStateForStart() {
return this.currentState().nextStateForStart();
}
...
}
public enum State {
ASSIGNED {
public State nextStateForstart() {
return ( State.IN_PROGRESS );
}
}
...
// more enum values for other states
...
// Default implementation of "start" transition
// It will be executed when the current state is not "ASSIGNED"
public State nextStateForstart() {
return null;
}
}
public void assertTaskIsValidForStart ( Task task ) {
Notification notification = new Notification();
// Validate the transition is allowed
if ( task.nextStateForStart() == null ) {
notification.addError(...);
}
...
// more errors
...
if ( notification.hasErrors() ) {
throw new TaskNotValidForStartException ( notification.errors() );
}
}
I think your enum does too much.
Besides having a fixed set of states which hardly can be extended, you make it hard to introduce any form of contract for each concrete state, which would also solve your notification problem.
Introduce an abstract state class which is the base class for all concrete states. A context is passed which allows setting a successor state for each state. This context can be implemented by your aggregate root.
Your notification can be managed by each state in a way you enforce using the AbstracftState, e.g. by forcing the state execution to return a notification object:
interface StateContext {
setState(AbstractState state);
}
class AbstractState {
abstract Notification execute(StateContext context);
}
class Task extends AggregateRoot implements StateContext {
AbstractState currentState;
....
public void start() {
Notification n = currentState.execute(this);
if (n.hasErrors()) {
throw new Exception(n.toErrorReport());
}
}
}
Now you can collect errors of each state before or after execution (you may want to introduce a validateStart() within each AbstractState which is called before execution) and report the collected errors to the caller.
I would model the TaskWorkflow as a VO inside the Task aggregate.
class Task {
private Workflow workflow;
public void start() {
workflow = workflow.followWith(Action.START, this);
}
public State currentState() {
return workflow.state();
}
public List availableActions() {
return workflow.nextActions();
}
}
The workflow is a FSM being composed of transitions between states joined by actions. Any call to a workflow method creates a new workflow representation pointing to the new state. Transitions can be modeled as direct or more complex custom involving business logic like you say.
If you use a functional language you can return a Monad to treat errors but in this case you can reify and create one or you can just throw an exception representing aggregated messages.
Hope it helps.
I have an MVC application in which I have to update the view with the current value of a stream.
In the model I have this method:
public Observable<Integer> getStreamInstance(){
if(stream == null){
this.stream = Observable.create((Subscriber<? super Integer> subscriber) -> {
new HeartbeatStream(frequence,subscriber).start();
});
}
return stream;
}
which I use in the controller to get the stream. Then, in the controller I have these two methods:
public void start(){
this.sb = stream.subscribe((Integer v) -> {
view.updateCurrValue(v);
});
}
public void stop(){
this.sb.unsubscribe();
}
With the start method I simply update a label in the view with the current value.
This works fine until I try to stop the updating with the unsubscribing; infact, when I press the button "stop" in the view, the label keeps updating with the current value and, if I press "start" again, the label shows the values from two different streams, the one that I first created with the first "start" and the second that seems has been created with the second pressing of "start".
Where am I wrong?
EDIT:
public class HeartbeatStream extends Thread{
private Subscriber<? super Integer> subscriber;
private int frequence;
private HeartbeatSensor sensor;
public HeartbeatStream(int freq, Subscriber<? super Integer> subscriber){
this.frequence = freq;
this.subscriber = subscriber;
sensor = new HeartbeatSensor();
}
public void run(){
while(true){
try {
subscriber.onNext(sensor.getCurrentValue());
Thread.sleep(frequence);
} catch (Exception e) {
subscriber.onError(e);
}
}
}
This is the HeartbeatStream class. HeartbeatSensor is a class that periodically generates a value that simulates the heartbeat frequence.
I'm guessing you tried to periodically signal some event that triggers the screen update. There is an operator for that:
Observable<Long> timer = Observable.interval(period, TimeUnit.MILLISECONDS,
AndroidSchedulers.mainThread());
SerialSubscription serial = new SerialSubscription();
public void start() {
serial.set(timer.subscribe(v -> view.updateCurrValue(v)));
}
public void stop() {
serial.set(Subscriptions.unsubscribed());
}
public void onDestroy() {
serial.unsubscribe();
}
Observable by design unsubscribe your observer once that all items are emitted and onComplete callback is invoked.
Look this example https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/creating/ObservableSubscription.java
I guess you're not handling the unsubscribe - although I can't see what's going on in your HeartbeatStream class.
If you're creating an Observable with Observable.create then you need to handle unsubscribing explicitly with subscriber.isUnsubscribed().
Where possible use some of the utility methods to create an Observable - they handle this all for you eg Observable.just() or Observable.from().
If this doesn't help, please post your HeartbeatStream class.
See the the docs for more details:
https://github.com/ReactiveX/RxJava/wiki/Creating-Observables
https://github.com/ReactiveX/RxJava/wiki/Async-Operators
I want to re-write a method that has way too many nested if statements.
I came up with this approach and wanted your opinions:
public void MyMethod()
{
bool hasFailed = false;
try
{
GetNewOrders(out hasFailed);
if(!hasFailed)
CheckInventory(out hasFailed);
if(!hasFailed)
PreOrder(out hasFailed);
// etc
}
catch(Exception ex)
{
}
finally
{
if(hasFailed)
{
// do something
}
}
}
I've done stuff similar to that, but without the exception handling:
BOOL ok = CallSomeFunction();
if( ok ) ok = CallSomeOtherFunction();
if( ok ) ok = CallYetAnotherFunction();
if( ok ) ok = WowThatsALotOfFunctions();
if( !ok ) {
// handle failure
}
Or if you want to be clever:
BOOL ok = CallSomeFunction();
ok &= CallSomeOtherFunction();
ok &= CallYetAnotherFunction();
...
If you are using exceptions anyway, why do you need the hasFailed variable?
Not really. Your methods should raise an exception in case of an error to be caught by your "catch" block.
As far as I can see this is an example of cascade steps where second and third one will be executed if first and first and second are valid, i.e. return hasFailed==false.
This code can be made much more elegant using Template Method and Decorator design pattern.
You need one interface, concrete implementation, abstract class and several subclasses of the abstract class.
public interface Validator {
public boolean isValid();
}
public class GetNewOrders implements Validator {
public boolean isValid() {
// same code as your GetNewOrders method
}
}
public abstract class AbstractValidator implements Validator {
private final Validator validator;
public AbstractValidator(Validator validator) {
this.validator = validator;
}
protected boolean predicate();
protected boolean isInvalid();
public final boolean isValid() {
if (!this.validator.isValid() && predicate() && isInvalid())
return false;
return true;
}
}
public class CheckInventory extends AbstractValidator {
public CheckInventory(Validator validator) {
super(validator);
}
#Override
public boolean predicate() {
return true;
}
#Override
public boolean isInvalid() {
// same code as your CheckInventory method
}
}
public class PreOrder extends AbstractValidator {
public CheckInventory(Validator validator) {
super(validator);
}
#Override
public boolean predicate() {
return true;
}
#Override
public boolean isInvalid() {
// same code as your PreOrder method
}
}
Now your method can look much more elegant:
public void MyMethod() {
bool success = false;
try {
Validator validator = new GetNewOrders();
validator = new CheckInventory(validator);
validator = new PreOrder(validator);
success = validator.isValid();
} finally {
if (!success) {
// do something
}
}
}
Validator object can be created in one line, but I prefer this style since it makes obvious the order of validation. Creating new validation link in the chain is matter of subclassing AbstractValidator class and implementation of predicate and isInvalid methods.
Without commenting on the try/catch stuff since I really don't know what is going on there, I would change it so the called methods return true/false for success and then just check them depending on the boolean short-circuiting to avoid calling later methods if the preceding method failed.
public void MyMethod()
{
bool success = false;
try
{
success = GetNewOrders()
&& CheckInventory()
&& PreOrder();
// etc
}
catch(Exception ex) { }
finally
{
if(!success)
{
}
}
}
This doesn't really look good to me. The use of the hasFailed variable is really not nice. if GetNewOrders fails with an exception, you for instance end up inside the catch block with hasFailed = false !
Opposed to other answers here I believe there MAY be legitimate uses for boolean "hasFailed" that are not exceptional. But I really don't think you should mix such a condition into your exception handler.
I know I'll probably duplicate a few posts: What's wrong with else? You could also use lazy evaluation (a() && b()) to link methods - but that relies on status being given as return value, which is more readable anyhow IMHO.
I don't agree with posters that you should raise an exception, because exceptions should be raised if program faults occur or the program enters an exceptional state because of operations. Exceptions are not business logic.
I would do it like this:
public void MyMethod()
{
bool success = false;
try
{
GetNewOrders(); // throw GetNewOrdersFailedException
CheckInventory(); // throw CheckInventoryFailedException
PreOrder(); // throw PreOrderFailedException
success = true;
}
catch( GetNewOrdersFailedException e)
{
// Fix it or rollback
}
catch( CheckInventoryFailedException e)
{
// Fix it or rollback
}
catch( PreOrderFailedException e)
{
// Fix it or rollback
}
finally
{
//release resources;
}
}
Extending an exception is rather trivial,
public NewExecption : BaseExceptionType {}
Well, I don't like code that appears to get a list of orders and then process them, and then stop processing them when an error occurs, when surely it should skip that order and move to the next? The only thing to completely fail on is when the database (source of orders, destination of preorders) dies. I think that the entire logic is a bit funky really, but maybe that's because I don't have experience in the language you are using.
try {
// Get all of the orders here
// Either in bulk, or just a list of the new order ids that you'll call the DB
// each time for, i'll use the former for clarity.
List<Order> orders = getNewOrders();
// If no new orders, we will cry a little and look for a new job
if (orders != null && orders.size() > 0) {
for (Order o : orders) {
try {
for (OrderItem i : o.getOrderItems()) {
if (checkInventory(i)) {
// Reserve that item for this order
preOrder(o, i);
} else {
// Out of stock, call the magic out of stock function
failOrderItem(o, i);
}
}
} catch (OrderProcessingException ope) {
// log error and flag this order as requiring attention and
// other things relating to order processing errors that aren't database related
}
}
} else {
shedTears();
}
} catch (SQLException e) {
// Database Error, log and flag to developers for investigation
}
Your new approach is not that bad for a simple set of instructions, but what happens when additional steps are added? Do you / would you ever require transactional behavior? (What if PreOrder fails? or If the next step after PreOrder fails?)
Looking forward, I would use the command pattern:
http://en.wikipedia.org/wiki/Command_pattern
...and encapsulate each action as a concrete command implementing Execute() and Undo().
Then it's just a matter of creating a queue of commands and looping until failure or an empty queue. If any step fails, then simply stop and execute Undo() in order on the previous commands. Easy.
Chris solution is the most correct. But I think you should not do more than you need. Solution should be extandable and that's enough.
Change value of a parameter is a bad practice.
Never use empty generic catch statement, at least add a comment why you do so.
Make the methods throw exception and handle them where it is appropriate to do so.
So now it is much more elegant :)
public void MyMethod()
{
try
{
GetNewOrders();
CheckInventory();
PreOrder();
// etc
}
finally
{
// do something
}
}