Avoiding LSP (Liskov Substitution Principles) violations - software-design

I'm currently reading the "Working Effectively with Legacy Code" by Michael Feathers
and I think I understand about the LSP violations, but the thing is it says something about the rules of thumb that help avoiding LSP violations which are,
Whenever possible, avoid overriding concrete methods.
If you do, see if you can call the method you are overriding in the overriding method.
I don't quite understand the number 2, could you help me clarify this please ?

I think, is the meaning:
class BaseClass
{
public virtual void MyFunc()
{
}
}
class DerivedClass : BaseClass
{
public override void MyFunc()
{
base.MyFunc();
}
}

Related

Testng assertj report and continue

I'm using AssertJ to test web using fluentlenium and extent reports for reporting the results.
I asked before the question but forgot to mention the use of AssertJ.
The provided answer was to extend soft assert and that it has onAssertFailure function.
Is there anything like this for AssertJ soft assertions? Or is there another solution to bypass it?
In the next AssertJ version (2.5.0) you will have access to all soft assertions errors (see this commit).
Hope it helps
In a future release of assertJ a method wasSuccess() is added (as can be seen on git history), but it is not yet available in the current release.
When this method is added you can do something like this:
public class AssertjSoftAssert extends SoftAssertions {
private void checkFailure() {
if(!wasSuccess()) {
onFailure();
}
}
private void onFailure() {
//doFailureStuff
}
#Override
public BigDecimalAssert assertThat(BigDecimal actual) {
BigDecimalAssert assertion = super.assertThat(actual);
checkFailure();
return assertion;
}
#Override
public BooleanAssert assertThat(boolean actual) {
BooleanAssert assertion = super.assertThat(actual);
checkFailure();
return assertion;
}
}
Do note, however, that you will have to override EVERY assertion method in the SoftAssertions class like I've shown you with the examples here. And also if new Assertions are added to the SoftAssertions class you will have to override those as well. This is the best solution I could find right now, but won't work until assertj is updated either.
EDIT: Actually I am not sure this would even work because I am not sure wasSuccess() will return true after every successvul softassert or only after throwing assertAll() but I can't test this obviously as the feature isn't out yet.
Bonus: The commit that added wasSuccess()

Understanding the relationship between Liskov and OCP

I am solidifying my understanding of the relationship between Liskov Substitutional Principal and Open Close Principal. If anybody could confirm my deductions and answer my questions below that would be great.
I have the following classes. As you can see, B is derived from A and it is overriding the DisplayMessage function in order to alter the behavior.
public class A
{
private readonly string _message;
public A(string message)
{
_message = message;
}
public virtual void DisplayMessage()
{
Console.WriteLine(_message);
}
}
public class B : A
{
public B(string message) : base(message){}
public override void DisplayMessage()
{
Console.WriteLine("I'm overwriting the expected behavior of A::DisplayMessage() and violating LSP >:-D");
}
}
Now in my bootstrap program, ShowClassTypeis expecting an object of Type A which should helpfully write out what class Type it is. However B is violating LSP so when it's DisplayMessage function is called it prints a completely unexpected message and essentially interferes with the intended purpose of ShowClassType.
class Program
{
static void Main(string[] args)
{
A a = new A("I am A");
B b = new B("I am B");
DoStuff(b);
Console.ReadLine();
}
private static void ShowClassType(A model)
{
Console.WriteLine("What Class are you??");
model.DisplayMessage();
}
}
So my question is, am I right to conclude that ShowClassType is now violating the Open Close Principal because now that Type B can come in and change the expected function of that method, it is no longer closed for modification (ie. to ensure it maintains it's expected behaviour you would have to alter it so that it first checks to make sure we are only working with an original A object)?
Or, inversely is this just a good example to show that ShowClassType is closed for modification and that by passing in a derived type (albeit a LSP violating one) we have extended what it is meant to do?
Lastly, is it bad practice to create virtual functions on Base classes if the base class is not abstract? By doing so, are we not just inviting derived classes to violate the Liskov Substitution principal?
Cheers
I'd say it's not ShowClassType that is violating the Open/Closed Principle.
It's only class B that is violating the Liskov Substitution Principle. A is Open for extension, but closed for modification.
From Wikipedia,
an entity can allow its behaviour to be modified without altering its source code.
It's obvious that the source code of A is not modified. Nor are private members of A being used (which would also be a violation of the Open/Closed principle in my book). B strictly uses the public interface of A, so although the Open/Closed principle is obeyed the Liskov Substitution Principle is violated.
The last question is worth a discussion in and of itself. A related question on SO is here.
I think it is not violate not LSP and not OCP in THIS context of using.
For my opinion, ShowClassType not violation OCP:
1. Function can not break OCP, only class architecture can do this.
2. You can add new behaviours to derived classes from A - so it do not break OCP
What about LSP? Your reason - user not expected get this message? But he got some message! If function overriding returns some message i think is ok in THIS context of your code.
If function, that add two numbers is overrides, and 1+1 returns 678 it not expectable for me and is bad. BUT, if for scientist of Physics from Mars planet it can be good answer.
DO NOT ANALYSE PROBLEM WITHOUT ALL CONTEXT!!! You must get whole picture of problem. And, of course

ASP.net how to extend a control or collection

I am attempting to extend a List. When using Visual Studio there are the different code hints for all the functions I can use with a List object. How can I extend the functionality of the List to show my new function?
public class ListExtensionHelper<T> : System.Collections.Generic.List<T>
{
public List<T> AwesomeFunction<T>()
{
}
}
For the life of me I could not find anything online on how I would do it for a List
If you are trying to add AwesomeFunction as an extension method to a regular List object, then you need to define an extension method in a static class:
public static class ListExtensions
{
public static List<T> AwesomeFunction<T>(this List<T> list)
{
}
}
Otherwise, the code you have should work; if you instantiate the ListExtensionHelper class, it should have all the functions of List as well as AwesomeFunction.
It sounds like you're looking for extension methods, rather than inheritance.
There are some really good examples here. There's also a really good library of extensions available here.
<soapbox>
One of my personal favorites that I use is this:
public static class StringExtensions
{
public static bool IsNullOrEmpty(this string s)
{
return string.IsNullOrEmpty(s);
}
}
It's ridiculously simple, but a huge pet peeve of mine is having to write:
if (string.IsNullOrEmpty(someVariable))
as opposed to:
if (someVariable.IsNullOrEmpty())
For me it's just a matter of being a natural construct of my native language. The built-in method sounds like:
object verb subject
whereas mine sounds like:
subject verb
It's probably silly, but when I want to act upon a subject it just makes more sense for me to start with the subject :)
</soapbox>

How do I reference a Global class from a class with the same name in ActionScript?

Due to requirements outside of my control (don't ask, it's ridiculous) I need to create an AS3 class called 'Math' that references the Global AS Math class. So, for example:
package my.package
{
public class Math
{
public static function pow( a:Number, b:Number ):Number {
// How do I call the Global.as$Math#pow(..) function?
return Math.pow(a,b);
}
}
}
The code above is clearly wrong - results in infinite recursion. I'm not sure how to say that I want to delegate to the Global.as$Math class and not this Math class...
My current awkward solution is to delegate to another class (not named Math) that passes through to the Global Math class. Is there a better way to do this?
Thanks!
Here is another way that popped into my mind after reading Josh Tynjala's post about how package in actionscript are just an abstraction layer over namespaces:
public class Math
{
namespace globalNs = "";
public static function pow( a:Number, b:Number ):Number
{
return globalNs::Math.pow(a, b);
}
}
The globalNs::Math.pow explicitly refer to the top level Math Class.
Save a static reference to the flash player Math object and use it throughout your static methods:
package test
{
import flash.utils.getDefinitionByName;
public class Math
{
private static var _flashMath:Class = Class(getDefinitionByName("Math"));
public static function pow( a:Number, b:Number ):Number
{
return _flashMath.pow(a, b);
}
}
}
Try using the AS3 namespace to refer to the AS3 Math object. Or your class could simply extend the Math object and it would automatically have all of the Math object's functionality without you having to rewrite all those wrapper functions.
As a small follow up on apphackers reply, you can not simple extends the AS3 Math object and have all it's functionality as was suggeested. Static methods are lost when extending an object since they are statically tied to the object which defines them. Additionally you can't extends a class with the same name. You might have some success with the namespace solution however, though I'm not sure if it'll work with static methods, I'd be interested to see your results.
Math is a special case in AS3 because really it shouldn't be global but it is. So it has no namespace as far as I can tell. The solution you came up with to route through another class is actually very clever. But you know that really the solution is to name the class Math2 or MathHelper or MathUtils rather than Math. Please tell me what the reason beyond your control is! The not knowing is killing me!!!

Is it possible to add behavior to a non-dynamic ActionScript 3 class without inheriting the class?

What I'd like to do is something like the following:
FooClass.prototype.method = function():String
{
return "Something";
}
var foo:FooClass = new FooClass();
foo.method();
Which is to say, I'd like to extend a generated class with a single method, not via inheritance but via the prototype.
The class is generated from a WSDL, it's not a dynamic class, and I don't want to touch the generated code because it will be overwritten anyway.
Long story short, I'd like to have the moral equivalent of C# 3:s Extension Methods for AS3.
Edit: I accepted aib's answer, because it fits what I was asking best -- although upon further reflection it doesn't really solve my problem, but that's my fault for asking the wrong question. :) Also, upmods for the good suggestions.
Yes, such a thing is possible.
In fact, your example is very close to the solution.
Try
foo["method"]();
instead of
foo.method();
#Theo: How would you explain the following working in 3.0.0.477 with the default flex-config.xml (<strict>true</strict>) and even a -compiler.strict parameter passed to mxmlc?
Foo.as:
package
{
public class Foo
{
public var foo:String;
public function Foo()
{
foo = "foo!";
}
}
}
footest.as:
package
{
import flash.display.Sprite;
public class footest extends Sprite
{
public function footest()
{
Foo.prototype.method = function():String
{
return "Something";
}
var foo:Foo = new Foo();
trace(foo["method"]());
}
}
}
Note that the OP said inheritance was unacceptable, as was modifying the generated code. (If that weren't the case, adding "dynamic" to the class definition would probably be the easiest solution.)
Depending on how many methods your class has, this may work:
Actual Class:
public class SampleClass
{
public function SampleClass()
{
}
public function method1():void {
Alert.show("Hi");
}
Quick Wrapper:
var actualClass:SampleClass = new SampleClass();
var QuickWrapper:Object = {
ref: actualClass,
method1: function():void {
this.ref.method1();
},
method2: function():void {
Alert.show("Hello!");
}
};
QuickWrapper.method1();
QuickWrapper.method2();
#aib is unfortunately incorrect. Assuming strict mode (the default compiler mode) it is not possible to modify the prototype of non-dynamic class types in ActionScript 3. I'm not even sure that it's possible in non-strict mode.
Is wrapping an option? Basically you create a class that takes one of the objects you get from the web service and just forwards all method calls to that, but also has methods of its own:
public class FooWrapper extends Foo {
private var wrappedFoo : Foo;
public function FooWrapper( foo : Foo ) {
wrappedFoo = foo;
}
override public function methodFromFoo( ) : void {
wrappedFoo.methodFromFoo();
}
override public function anotherMethodFromFoo( ) : void {
wrappedFoo.anotherMethodFromFoo();
}
public function newMethodNotOnFoo( ) : String {
return "Hello world!"
}
}
When you want to work with a Foo, but also have the extra method you need you wrap the Foo instance in a FooWrapper and work with that object instead.
It's not the most convenient solution, there's a lot of typing and if the generated code changes you have to change the FooWrapper class by hand, but unless you can modify the generated code either to include the method you want or to make the class dynamic I don't see how it can be done.
Another solution is to add a step to your build process that modifies the source of the generated classes. I assume that you already have a step that generates the code from a WSDL, so what you could do is to add a step after that that inserts the methods you need.
Monkey patching is an (inelegant) option.
For example, suppose you don't like the fact that Flex 3 SpriteAsset.as returns a default border metrics of [7,7,7,7] (unlike flex 2). To fix this, you can:
Create a copy of SpriteAsset.as and add it to your project at /mx/core/SpriteAsset.as
Edit your local copy to fix any problems you find
Run your ap
Google "flex monkey patch" for more examples and instructions.

Resources