2 (+1) Requirements
1.- The user must be able to add many types of Equipment
2.- When the type of equipment is "SOME VALUE" then ...
N.- ... future requirement ... now when the type of equipment is "SOME OTHER VALUE" then ...
The situation is that in one side, I know that the "Types" could change, but also I know that some values must exist particular values of "Type" in order to perform particular behaviors.
private int SomeAction(Equipment e)
{
if (e.Type == "SOME VALUE")
{
// Do something for that special case
}
else if (e.Type == "SOME OTHER VALUE")
{
// Do something for that other special case
}
else
{
// Do the other thing
}
}
One option is to put the logic into the Equipment class as suggested by #NicoGranelli in the above comment. This is a good approach especially if you have different subclasses of Equipment
Another alternative is factor out an Action interface. You would have different Action implementations and map each equipment type to a specific action. With this approach you eliminate the conditionals. It also facilitates unit testing of each Action implementation.
interface EquipmentAction { void perform(); }
class SomeAction implements EquipmentAction { void perform() { ... } }
class SomeOtherAction implements EquipmentAction { void perform() { ... } }
class DefaultAction implements EquipmentAction { void perform() { ... } }
class Client {
private final Map<EquipmentType,EquipmentAction> equipmentActions = buildEquipmentActionMap();
private final EquipmentAction DEFAULT_ACTION = new DefaultAction();
private int SomeAction(Equipment equipment) {
EquipmentAction action = equipmentActions.getOrDefault(equipment.Type, DEFAULT_ACTION);
action.perform();
}
}
Related
I have a Value interface with a method to show value as a string.
Usually the value is an integer so IntegerValue implements Value.
Sometimes value is unknown which I use null object pattern for so UnknownValue implements Value.
When the value is actually an integer, it's useful for the client to check whether the value is high enough (IntegerValue.isEnough). This affects how this value is displayed to the user later on. However, if the value is unknown, it doesn't make sense to check if it's high enough--the value is unknown. By the Interface Segregation Principle, UnknownValue should not have an isEnough method.
interface Value {
toString(): string;
}
class IntegerValue implements Value {
private value: number;
constructor(v: number) { this.value = v }
isEnough() { return this.value >= 30 }
toString() { return '' + this.value }
}
class UnknownValue implements Value {
toString() { return 'unknown' }
}
But the client accesses a Value and won't know whether it's an IntegerValue. So I'd have to check and then typecast it.
if(value.toString() !== 'unknown') {
handleInteger(value as IntegerValue) // <-- check if isEnough inside
} else {
handleUnknown(value)
}
I was wondering if there was a design pattern that could solve this with polymorphism, without typecasting.
I was considering the Visitor Pattern like so:
interface ValueVisitor {
handleInteger(v: IntegerValue): void;
handleUnknown(): void
}
class ViewValueVisitor implements ValueVisitor { ... }
class JsonSerializerValueVisitor implements ValueVisitor { ... }
interface Value {
toString(): string;
acceptVisitor(v: ValueVisitor): void;
}
class IntegerValue implements Value {
...
acceptVisitor(v) { v.handleInteger(this) }
}
class UnknownValue implements Value {
...
acceptVisitor(v) { v.handleUnknown() }
}
But the Visitor Pattern violates the Open Closed Principle. I was wondering if there is a better solution.
This answer is very contrived for the problem scope of the default behavior of some value object and its Interface Segregation Principle violation. We can usually afford to sin a little and just type-cast or check the class in the client with value instanceof IntegerValue or value.getType() === 'integervalue'.
But the inherent problem is not confined to only this problem scope. What happens when you have different classes implementing an interface that must be treated differently in the client. When there are more types involved, we may want to follow the SOLID principles to improve cohesion and encapsulation.
Also not sure if this answer is supported by languages other than typescript, but...
I think I got very close with my visitor pattern solution. Just needed one tweak so that the visitor pattern doesn't break the OCP. We can do that with the strategy pattern.
enum HandledTypes {
IntegerValue,
UnknownValue,
...
}
interface ValueHandler {
type: HandledType;
handle(value: Value): void;
}
class ValueVisitor {
handlers: Map<HandledTypes, ValueHandler>;
constructor(handlers: ValueHandler[]) { ... }
handle(key: HandledTypes, v: Value) {
const h = this.handlers.get(key)
h.handle(v);
}
}
// a handler would expect a more specific type
class ViewIntegerValueHandler implements ValueHandler {
readonly type = HandledTypes.IntegerValue;
handle(value: IntegerValue) { ... }
}
interface Value {
toString(): string;
acceptVisitor(v: ValueVisitor): void;
}
class IntegerValue implements Value {
...
acceptVisitor(v) { v.handle(HandledTypes.IntegerValue, this) }
}
class UnknownValue implements Value {
...
acceptVisitor(v) { v.handle(HandledTypes.UnknownValue, this) }
}
Now we can compose a ValueVisitor with all the types it needs to handle within the client.
function doSomething(value: Value) {
const viewValueVisitor = new ValueVisitor([
new ViewIntegerValueHandler(),
new ViewUnknownValueHandler(),
]);
value.acceptVisitor(viewValueVisitor);
}
One problem with this is that I don't see how TypeScript can warn you about providing the incorrect HandledTypes key to ValueVisitor.handle which may lead to a problem at runtime that may or may not throw an error.
Is it ok for an Observer object to call notifyListeners() on an observable after changing some of its fields? What disadvantages could arise? Usually it's the subjects' responsibility to notify listeners of changes.
I frequently come across the following problem when wrapping model classes in an observable / subject e.g. to make them accessible in UI.
Should my subject notify its listeners whenever any field of the model object is changed or should I provide some kind of method setModel() that takes a new model object as an argument and only then notifies all listeners?
For example:
class MyData {
String myString;
int myInt;
}
class MyDataObservable {
private MyData data;
// constructor
void setString(String string) {
data.myString = string;
notifyListeners();
}
void setInt(int num) {
data.myInt = num;
notifyListeners();
}
void notifyListeners() {...}
void addListener(Observer o) {...}
}
I don't like that my subject basically mirrors all the properties of my model .. which is pretty ugly.
class MyDataObservable {
private MyData data;
// constructor
void setData(MyData data) {
this.data = data;
notifyListeners();
}
void notifyListeners() {...}
void addListener(Observer o) {...}
}
The downside of this approach is that I have to build a new copy of my data class everytime anything changes, even if it's just a bool flag on my model class.
So my idea was to allow for observers to notify other listeners when they changed something with e.g. an update function.
Are there other, more elegant alternatives?
EDIT
At the moment, making my data class an observable is not an option because I'm using a framework that provides an observable mechanism that can also hold business logic. For that reason I want to decouple my data class and the logic / observable.
In this case I would use inheritance rather than composition: MyData is-a Observable rather than Observable has-a MyData.
class Observable {
Collection<Listener> listeners
void addListener(Listener l) {...}
void notifyListeners() {...}
}
class MyData extends Observable {
String myString;
int myInt;
void setString(String string) {
this.myString = string;
notifyListeners();
}
void setInt(int num) {
this.myInt = num;
notifyListeners();
}
}
I am looking for specialized singleton implementation, probably I might be using wrong terminology and hence looking for expert suggestion. Here is my scenario:
There is common code which can be called by ComponentA or ComponentB. I need to push telemetry data from the common code. Telemetry needs to have information that whether this common code get called by ComponentA or ComponentB.
So common code will have just this line of code:
telemetry.pushData(this._area, data);
where this._area tells the telemetry data is getting pushed for which component
I need to push telemetry data from multiple places so it would be good if object got created once and used through out the code lifetime
One option I can think of passing component context to the common code which in mind doesn't look right, hence looking for suggestion what kind of pattern one should use in this case?
This is what I am thinking
// Telemetry.ts file present in shared code
export class Telemetry extends Singleton {
public constructor() {
super();
}
public static instance(): Telemetry {
return super.instance<Telemetry>(Telemetry);
}
public publishEvent(data): void {
if (!this.area) {
throw new Error("Error: Initialize telemetry class with right area");
}
pushtelemetryData(this.area, data);
}
public area: string;
}
// Create Telemetry object from component A
Telemetry.instance().area = "ComponentA";
// Shared code will call telemetry publishEvent
Telemetry.instance().publishEvent(data);
Thanks
It's not a good pattern to use in TypeScript where you would generally inject dependencies.
If you must absolutely do it then you can do it by faking it somewhat:
namespace Telemetry {
var instance : SingletonSomething;
export function push(data: Any) : void {
if (instance == null) {
instance = new SingletonSomething();
}
instance.push(data);
}
class SingletonSomething() { ... }
}
and then you could call
Telemetry.push(data);
You can imitate the singleton pattern in typescript easily:
class Telemetry {
private static instance: Telemetry;
public static getInstance(): Telemetry {
if (Telemetry.instance == null) {
Telemetry.instance = new Telemetry();
}
return Telemetry.instance;
}
...
}
If you have your code in some sort of closure (module, namespace, etc) then you can replace the static member with:
let telemetryInstance: Telemetry;
export class Telemetry {
public static getInstance(): Telemetry {
if (telemetryInstance == null) {
telemetryInstance = new Telemetry();
}
return telemetryInstance;
}
...
}
But then you can also replace the static method with:
let telemetryInstance: Telemetry;
export function getTelemetryInstance(): Telemetry {
if (telemetryInstance == null) {
telemetryInstance = new Telemetry();
}
return telemetryInstance;
}
export class Telemetry {
...
}
At this point, in case you are using some sort of closure, you might ask yourself if you really need the class at all?
If you use this as a module:
// telemetry.ts
export interface TelemetryData {
...
}
export function pushData(data: TelemetryData): void {
...
}
Then you get exactly what you're looking for, and this is more of the "javascript way" of doing it.
Edit
In the telemetry module there's no need to know the users of it.
If the Telemetry.pushData function needs to have information about the object that called it then define an interface for it:
// telemetry.ts
export interface TelemetryData {
...
}
export interface TelemetryComponent {
name: string;
...
}
export function pushData(data: TelemetryData, component: TelemetryComponent): void {
...
}
Then in the other modules, where you use it:
// someModule.ts
import * as Telemetry from "./telemetry";
class MyComponent implement Telemetry.TelemetryComponent {
// can also be a simple string property
public get name() {
return "MyComponent";
}
fn() {
...
Telemetry.pushData({ ... }, this);
}
}
2nd Edit
Because you are using a module system, your module files are enough to make singletons, there's no need for a class to achieve that.
You can do this:
// telemetry.ts
let area: string;
export interface TelemetryData {
...
}
export function setArea(usedArea: string) {
area = usedArea;
}
export function pushData(data: TelemetryData): void {
...
}
Then:
Telemetry.setArea("ComponentA");
...
Telemetry.publishEvent(data);
The telemetry module will be created only once per page, so you can treat the entire module as a singleton.
Export only the functions that are needed.
I have this abstract class:
public abstract class Accessor<T extends Id, U extends Value>
{
public U find(T id)
{
// let's say
return getHelper().find(id);
}
}
And an implementation:
public FooAccessor extends Accessor<FooId,Foo>
{
public Helper getHelper
{
// ...
return helper;
}
}
And I would like to mock the calls to FooAccessor.find.
This:
#MockClass(realClass=FooAccessor.class)
static class MockedFooAccessor
{
public Foo find (FooId id)
{
return new Foo("mocked!");
}
}
will fail with this error:
java.lang.IllegalArgumentException: Matching real methods not found for the following mocks of MockedFooAccessor:
Foo find (FooId)
and I understand why... but I don't see how else I could do it.
Note: yes, I could mock the getHelper method, and get what I want; but this is more a question to learn about JMockit and this particular case.
The only way around this I have found is to use fields
#Test
public void testMyFooMethodThatCallsFooFind(){
MyChildFooClass childFooClass = new ChildFooClass();
String expectedFooValue = "FakeFooValue";
new NonStrictExpectations(){{
setField(childFooClass, "fieldYouStoreYourFindResultIn", expectedFooValue);
}};
childFooClass.doSomethingThatCallsFind();
// if your method is protected or private you use Deencapsulation class
// instead of calling it directly like above
Deencapsulation.invoke(childFooClass, "nameOfFindMethod", argsIfNeededForFind);
// then to get it back out since you used a field you use Deencapsulation again to pull out the field
String actualFoo = Deencapsulation.getField(childFooClass, "nameOfFieldToRunAssertionsAgainst");
assertEquals(expectedFooValue ,actualFoo);
}
childFooClass doesn't need to be mocked nor do you need to mock the parent.
Without more knowledge of your specific case this strategy has been the best way for me to leverage jMockit Deencapsulation makes so many things possilbe to test without sacrificing visibility. I know this doesn't answer the direct question but I felt you should get something out of it. Feel free to downvote and chastise me community.
Honestly, I do not find it in any way different from mocking regular classes. One way to go is to tell JMockit to mock only the find method and use Expectations block to provide alternate implementation. Like this:
abstract class Base<T, U> {
public U find(T id) {
return null;
}
}
class Concrete extends Base<Integer, String> {
public String work() {
return find(1);
}
}
#RunWith(JMockit.class)
public class TestClass {
#Mocked(methods = "find")
private Concrete concrete;
#Test
public void doTest() {
new NonStrictExpectations() {{
concrete.find((Integer) withNotNull());
result = "Blah";
}}
assertEquals("Blah", concrete.work());
}
}
Hope it helps.
I have class with 2 methods
class A
{
void Fun()
{
if(FunRet()>0){///} else {///}
}
int FunRet()
{ return 4;}
};
I want to test Fun() method depend on what FunRet returns. So i want to mock FunRet.
I rather don't want make FunRet as virtual. How I can do that?
You can inject intra-class dependencies. In this case, make Fun accept a value instead of computing it:
class A
{
void Fun(int x)
{
if(x>0){///} else {///}
}
int FunRet()
{ return 4;}
};
Then your tests can pass arbitrary values into Fun(). If you need to enforce correct use, write a public version to expose in your API and a private version for testing:
class A {
public:
void Fun() { return Fun(FunRet()); }
private:
void Fun(int x); // for testing.
};
You could extract the Fun method into a calculator class that implements an interface. You should pass an instance of that interface to class A at constructor.
In testing you could have other classes implementing that interface, that return other values.
This method also have the big advantage, that you seperate the concerns of calculating a value and using the calculated value.
class A {
public:
A (IFunCalc calc) { m_calc = calc; }
void Fun { if calc.FunRet() > 4 ... }
private:
IFunCalc m_calc;
}
class FunCalc : IFunCulc {
public:
int FunRet { return 4; }
}
class FunCalc4Test : IFunCalc {
public:
int FunRet { return 27; }
}
I think you're missing the this pointer.
... if ( this->FunRet() > 0 ) { ...
If you use dependency injection and template your object under test, you can use mock objects without having to use virtual functions.
class AParameters
{
public:
int FunRet()
{ return 4;}
};
class MockAParameters
{
public:
MOCK_METHOD0(FunRet, int());
};
template<class Parameters>
class AImpl
{
public:
AImpl(Parameters& parameters):parameters(parameters){}
void Fun()
{
if(parameters.FunRet()>0){///} else {///}
}
private:
Parameters& parameters;
};
typedef AImpl<AParameters> A;
typedef AImpl<MockAParameters> ATestObject;
void Test::funUsesFunRet()
{
MockAParameters params;
EXPECT_CALL(params, FunRet());
ATestObject object(params);
object.Fun();
}
I believe FunRet is an internal implementation detail of Fun. As a result, Fun does not need to be tested in isolation from FunRet. Just test Fun and don't worry about the fact it calls FunRet.