"Base class params are not always used" code smell - c#

Suppose you had such code:
public Base
{
abstract void Register();
}
public Registrator1: Base
{
override void Register()
{
//uses the current state of the object to populate the UI captions
}
}
public Registrator2: Base
{
override void Register()
{
//uses the current state of the object to populate the UI captions
}
}
But When you receive a new business rule asking you to write Registrator3 which actually registers based on some parameter and you change your code base to the next:
public Base
{
abstract void Register(externalParam);
}
public Registrator1: Base
{
override void Register(externalParam)
{
//uses the current state of the object to populate theUI
}
}
public Registrator2: Base
{
override void Register(externalParam)
{
//uses the current state of the object to populate the UI
}
}
public Registrator3: Base
{
override void Register(externalParam)
{
//uses a DDD - service passed in the params to populate the UI
}
}
But Registrator1 and Registrator2 do not need that param and the code becomes smelly. What are the ways to re-write this code?

You could use an object as a parameter here; which is commonly used in scenarios where the number of parameters can vary depending on the call being used.
struct RegistrationInfo
{
public static readonly RegistrationInfo Empty = new RegistrationInfo();
public string Username;
public string CustomerName;
public string Validity;
}
abstract class Base
{
public abstract void Register(RegistrationInfo info);
// If you want to retain the paramaterless call:
public void Register()
{
Register(RegistrationInfo.Empty);
}
}
class Registrar1 : Base
{
public override void Register(RegistrationInfo info)
{
if (info.Username == null) throw new ArgumentNullException("info.Username");
}
}
class Registrar2 : Base
{
public override void Register(RegistrationInfo info)
{
if (info.CustomerName == null) throw new ArgumentNullException("info.CustomerName");
}
}
This has the advantage that you don't need to change method parameters (which is breaking interface) each time a parameter is added. The usage also becomes somewhat self-documenting:
var r = new Registrar1();
r.Register(new RegistrationInfo(){ Username = "JimJoe" });
r.Register(RegistrationInfo.Empty);
It's like air freshener for this type of code smell, while it's still smelly; you can make it smell nicer.
Finally you can make the call-site cleaner by making it a params argument (this has a small amount of overhead); in all honesty though it is more smelly because it's a language hack. Finally you could improve it with generics:
class RegistrationInfo
{
}
class RegistrationInfo1 : RegistrationInfo
{
public string Arg;
}
class RegistrationInfo2 : RegistrationInfo
{
public int Arg;
}
interface IBase<in TRegistration>
where TRegistration : RegistrationInfo
{
void Register(TRegistration registration);
}
class Base : IBase<RegistrationInfo>
{
public void Register(RegistrationInfo registration)
{
}
}
class Registrar1 : IBase<RegistrationInfo1>
{
public void Register(RegistrationInfo1 arg)
{
}
}
class Registrar2 : IBase<RegistrationInfo2>
{
public void Register(RegistrationInfo2 arg)
{
}
}

Is it not possible to contain the logic for externalParam in Registrator3?
In other words, Registrator3 uses the param, then calls the unmodified parameterless base?
A lot really depends on where the logic belongs. If it is something intrinsic to the base, then put it in the base, and either overload the Register() function or supply a default value for the param so that sub classes don't need to provide it.

Assuming you want to reuse the registration logic from the base class, you could update the code as follows:
public class Base
{
public virtual void Register(object externalParam)
{
// base registration logic goes here
}
}
public class Registrator1: Base
{
public override void Register(object externalParam)
{
base.Register(null);
// custom registration logic goes here
}
}
public class Registrator2: Base
{
public override void Register(object externalParam)
{
base.Register(null);
// custom registration logic goes here
}
}
public class Registrator3: Base
{
public override void Register(object externalParam)
{
base.Register(externalParam);
// custom registration logic goes here
}
}
HTH,
Cosmin
EDIT: Updated code to compile.

Related

How to implement a factory pattern based on argument types?

I have PhotoBase class
public abstract class PhotoBase
{
public string Path { get; set; }
}
And I have multiple derived classes, for example the path may indicate a location in the file system or an external url.
public class FilePhoto : PhotoBase {}
public class ExternalPhoto : PhotoBase {}
I want to load these photos, I have a PhotoLoader class like below:
public class PhotoLoader
{
public void Load(FilePhoto Photo)
{
// get the photo from file system
}
public void Load(ExternalPhoto Photo)
{
// download the photo from path
}
}
Now I want to load these photos, so I have to do:
public class PhotoImporter
{
private PhotoLoader _photoLoader;
public PhotoImporter(PhotoLoader photoLoader)
{
_photoLoader = photoLoader;
}
public void ImportPhoto(PhotoBase photo)
{
if (photo is FilePhoto)
{
_photoLoader.Load(photo as FilePhoto);
}
if (photo is ExternalPhoto)
{
_photoLoader.Load(photo as ExternalPhoto);
}
}
}
I have several derived classes and I may add more photo types in the future. Is there a more elegant way that I could get rid of if conditions? Using factory pattern?
Another approach would be to have an abstract method Load on PhotoBase, that's then implemented by each subclass:
public abstract class PhotoBase
{
public string Path { get; set; }
public abstract void Load();
}
public class FilePhoto : PhotoBase
{
public override void Load()
{
// load from file system
}
}
public class ExternalPhoto : PhotoBase
{
public override void Load()
{
// load from path
}
}
That way, you can simply call the Load method on a PhotoBase:
public class PhotoImporter
{
public void ImportPhoto(PhotoBase photo)
{
photo.Load();
}
}
The main advantage is that each subclass implements the Load method, and therefore you can add as many subclasses as you want, without worrying about forgetting to implement it.
The main drawback to this implementation is that the Load methods can't depend on other dependencies. So for example, if one day you need to load a photo from a database, you can't pass the DBContext.
Proper to way to implement it which will make code easy to maintain is as follows:
public abstract class PhotoBase
{
public string Path { get; set; }
public abstract void Load(); // Have a abtract method
}
public class FilePhoto : PhotoBase {
public override void Load() { // Implement the abtract method
Console.WriteLine("FilePhoto");
}
}
public class ExternalPhoto : PhotoBase {
public override void Load() { // // Implement the abtract method
Console.WriteLine("ExternalPhoto");
}
}
public class PhotoLoader
{
private PhotoBase _PhotoBase;
public PhotoLoader(PhotoBase photoBase) { // Resolved by Dependency Injection
_PhotoBase = photoBase;
}
public void Load()
{
_PhotoBase.Load();
}
}
public class PhotoImporter
{
private PhotoLoader _photoLoader;
public PhotoImporter(PhotoLoader photoLoader) // Resolved by Dependency Injection
{
_photoLoader = photoLoader;
}
public void ImportPhoto()
{
_photoLoader.Load();
}
}
You need to have Dependency Injection define so that specified implementation will get resolved and appropriate 'Load' method will be invoked.
void Main()
{
// Following dependency should be resolved by Dependency Injection
PhotoBase filePhotoBase = new FilePhoto();
PhotoLoader filePhotoLoader = new PhotoLoader(filePhotoBase);
PhotoImporter filePhotoImporter = new PhotoImporter(filePhotoLoader);
PhotoBase externalPhotoBase = new ExternalPhoto();
PhotoLoader externalPhotoLoader = new PhotoLoader(externalPhotoBase);
PhotoImporter externalPhotoImporter = new PhotoImporter(externalPhotoLoader);
filePhotoImporter.ImportPhoto(); // Shows output 'FilePhoto'
externalPhotoImporter.ImportPhoto(); // Shows output 'ExternalPhoto'
}
You can have as much implementation as you want, but you need to have proper instance of PhotoImporter by Dependency Injection. Everything else will work smoothly.
This is how I could do this:
public class PhotoImporter
{
private PhotoLoader _photoLoader;
public PhotoImporter(PhotoLoader photoLoader)
{
_photoLoader = photoLoader;
}
public void ImportPhoto(PhotoBase photo)
{
var childType = photo.GetType();
dynamic childPhoto = Convert.ChangeType(photo, childType);
_photoLoader.Load(childPhoto);
}
}
You can simplify your ImportPhotoby using pattern matching:
public void ImportPhoto(photoBase photo)
{
switch(photo)
{
case FilePhoto filePhoto:
loader.Load(filePhoto);
break;
case ExternalPhoto externalPhoto:
loader.Load(externalPhoto);
break;
}
}
But this is only syntactic sugar and doesn't solve your real problem. What might help is a abstract Load method in your base class:
public abstract class PhotoBase
{
public string Path { get; set; }
public abstract void Load();
}
You have to implement this method in your child classes. If you call the method, the correct implementation will be chosen.
Online demo: https://dotnetfiddle.net/LfkxBQ

Reuse without casting to class from interface

I want to reuse Cook method functionality, but still pass different parameters to execute:
public void Cook(BasicRequest request,IBaseInterface base)
{
// Some code
// More code
request.Execute(base);
}
public class BasicRequest
{
public abstract void Execute(IBaseInterface baseInterface)
}
public class RequestA : BasicRequest
{
public void Execute(IBaseInterface base)
{
var derived = (DerivedClassA)base;
// Do stuff with derived
}
}
public class RequestB : BasicRequest
{
public void Execute(IBaseInterface base)
{
var derived = (DerivedClassB)base;
// Do stuff with derived
}
}
public interface IDerivedClassA : IBaseInterface {}
public interface IDerivedClassB : IBaseInterface {}
I have a design issue here that casting is needed on each of requests execute methods.
How can I make this code cleaner ?
You should be using generics.
Update the BaseRequest to a generic class:
public abstract class BasicRequest<T> where T:IBaseInterface
{
public abstract void Execute(T baseInterface);
}
Change your class Cook method as follows:
public void Cook<T>(BasicRequest<T> request, T ibase) where T:IBaseInterface
{
// Some code
// More code
request.Execute(ibase);
}
Change your classes,
public class RequestA : BasicRequest<DerivedClassA>
{
public override void Execute(DerivedClassA ibase)
{
// Do stuff with derived
}
}
public class RequestB : BasicRequest<DerivedClassB>
{
public override void Execute(DerivedClassB ibase)
{
// Do stuff with derived
}
}

Overloading abstract generic methods in C#

I'm trying to implement a generic abstract method with a type constraint, then Implement it multiple times using different specified types.
public abstract class Ability
{
public abstract void BindToStation<T>(T station) where T : Station;
}
public class DashAbility : Ability
{
public override void BindToStation<NavStation>(NavStation station){ }
public override void BindToStation<CannonStation>(CannonStation station){ }
}
But I get an error which says the method has already been defined with the same paramater types.
I'm guessing that the compiler treats any generic paramater as the same in terms of the method signature, so these two methods look the same to it.
Still though, I'm wondering if theres a way to have generic method overloading using specific types.. ?
You can't do exactly what you want, but you can try an approach like this:
interface IBindableTo<T> where T : Station
{
void BindToStation(T station);
}
abstract class Ability
{
public abstract void BindToStation<T>(T station) where T : Station;
}
class DashAbility : Ability, IBindableTo<NavStation>, IBindableTo<CannonStation>
{
public override void BindToStation<T>(T station)
{
if (this is IBindableTo<T> binnder)
{
binnder.BindToStation(station);
return;
}
throw new NotSupportedException();
}
void IBindableTo<NavStation>.BindToStation(NavStation station)
{
...
}
void IBindableTo<CannonStation>.BindToStation(CannonStation station)
{
...
}
}
Hope this helps.
C# doesn't support specialization in that way, and neither does C++ easily when you want to specialize on runtime type.
But you can use polymorphism, so you can use double-dispatch:
public abstract class Station {
internal abstract void DashBindToStation();
}
public class NavStation : Station {
internal override void DashBindToStation() {
throw new NotImplementedException();
}
}
public class CannonStation : Station {
internal override void DashBindToStation() {
throw new NotImplementedException();
}
}
public abstract class Ability {
public abstract void BindToStation(Station station);
}
public class DashAbility : Ability {
public override void BindToStation(Station station) {
station.DashBindToStation();
}
}
Another possibility with C# is to use runtime dispatching using dynamic:
public abstract class Station {
}
public class NavStation : Station {
}
public class CannonStation : Station {
}
public abstract class Ability {
public abstract void BindToStation(Station station);
}
public class DashAbility : Ability {
public void BindToStation(NavStation station) {
}
public void BindToStation(CannonStation station) {
}
public override void BindToStation(Station station) {
BindToStation((dynamic)station);
}
}

C# Factory Pattern - Base method will always get called

I'm wondering why in the following example does the base method always get called even though I'm overriding it when the Factory Pattern "Builder" returns a new instance of the object?
interface FactoryInter
{
void MakeDetails();
}
class Builder {
public static Builder getObject(string obj)
{
if(obj == "Cont")
{
return new Cont();
}else{
return new Builder();
}
}
public void MakeDetails()
{
Console.WriteLine("I will always get called..");
}
}
class Cont : Builder, FactoryInter {
public void MakeDetails()
{
Console.WriteLine("Hello..");
}
}
public class Test
{
public static void Main()
{
Builder b = new Builder();
b = Builder.getObject("Cont");
b.MakeDetails();
// your code goes here
}
}
Any help would be greatly appreciated
You do not override it. You are hiding it. Method Cont.MakeDetails() is hiding the base class's MakeDetails method. For more details please see the below example:
class Base
{
public void Hidden()
{
Console.WriteLine("Base!");
}
public virtual void Overrideable()
{
Console.WriteLine("Overridable BASE.");
}
}
class Derived : Base
{
public void Hidden()
{
Console.WriteLine("Derived");
}
public override void Overrideable()
{
Console.WriteLine("Overrideable DERIVED");
}
}
Now testing them yields these results:
var bas = new Base();
var der = new Derived();
bas.Hidden(); //This outputs Base!
der.Hidden(); //This outputs Derived
((Base)der).Hidden();
//The above outputs Base! because you are essentially referencing the hidden method!
//Both the below output Overrideable DERIVED
der.Overrideable();
((Base)der).Overrideable();
To override it, mark the base method as virtual and the derived one as override.

Inheritance and classes within classes

Here's some pseudo code to illustrate what I'm looking at.
public class Loader
{
public Execute()
{
var currentPage = new ItemPageDocumentBuilder();
while(reader.Read())
{
currentPage.Add(reader.XmlDoc);
}
}
private class ItemsToLoad
{
private XmlDocument _page
public void Add(XmlElement itemelement)
{
_page.DocumentElement.AppendChild(itemElement);
}
}
}
I need to derive a class from Loader, and then override the Add method of the ItemsToLoad class inside it, and then call base.Execute(). In other words I want the Execute() method of my derived class to be exactly the same as that of Loader, but to use the overridden Add method of ItemsToLoad to to its work.
I suspect the neatest way to do this would be to remove ItemsToLoad from inside Loader, and make it abstract, correct?
If I couldn't do that, out of interest, what's the best solution?
If I understand your requirement, you have two responsabilities: executing something (which is always the same), and adding something (which differs).
I would do it much simpler, without inheritance and inner classes.
For the adding task, you define an interface:
public interface IItemAdder
{
void Add();
}
And one ore more implementations:
public class ItemAdder1 : IItemAdder
{
public void Add()
{
// specific implementation here
}
}
Then, you have a Loader, in which you inject a specific instance of item adder:
public class Loader : ILoader
{
private IItemAdder _itemAdder;
public Loader(IItemAdder itemAdder)
{
_itemAdder = itemAdder;
}
public void Execute()
{
// use injected item adder to do work
_itemAdder.Add();
}
}
public interface ILoader
{
void Execute();
}
And so usage is:
var loader = new Loader(new ItemAdder1());
loader.Execute();
This way everything is injected, can be replaced and mocked easily; and you clearly separate concerns.
Here is a suggestion (Syntax might not be correct though):
public class Loader
{
ItemsToLoad item;
public Loader(ItemsToLoad item) {
this.item = item;
}
public Execute()
{
// do things using item like item.add();
}
}
interface ItemsToLoad
{
void add();
}
class ItemsToLoad1: ItemsToLoad
{
void add(){
// implementation
}
}
class ItemsToLoad2: ItemsToLoad
{
void add(){
// implementation
}
}
And here is how to use them;
ItemsToLoad item;
if (some condition) {
item = new ItemsToLoad1()
} else {
item = new ItemsToLoad2()
}
Loader loader = new Loader(item);
loader.execute();
You can inherit both classes and inject child sub-class object to its parent.
class Loader
{
public void Execute(ItemsToLoad argObj)
{
if(argObj == null)
argObj = new ItemsToLoad();
argObj.Add(19);
}
public class ItemsToLoad
{
public virtual void Add(int a)
{
Console.WriteLine("Reached ItemsToLoad.");
}
}
}
class ChildLoader:Loader
{
public void Execute(ItemsToLoad argObjLoader)
{
if (argObjLoader == null)
argObjLoader = new ChildItemsToLoad();
base.Execute(argObjLoader);
}
class ChildItemsToLoad : Loader.ItemsToLoad
{
public override void Add(int b)
{
Console.WriteLine("Reached ChildItemsToLoad.");
}
}
}
And can start with
ChildLoader obj999 = new ChildLoader();
obj999.Execute(null);
I need to derive a class from Loader, and then override the Add method of the ItemsToLoad class inside it, and then call base.Execute(). In other words I want the Execute() method of my derived class to be exactly the same as that of Loader, but to use the overridden Add method of ItemsToLoad to to its work.
You need to override Loader, not ItemsToLoad. You haven't shown the code that uses ItemsToLoad, so it's difficult to be specific - but at the very least, you would need to override the new ItemsToLoad to point to your subclass. Also, ItemsToLoad is private - meaning you can't use it except from within Loader. As it is now, you'd need a completely rewritten ItemsToLoad and to override every method in Loader that uses ItemsToLoad.
If you control the Loader class, the easiest changes would probably be to abstract out the creating of ItemsToLoad and open up ItemsToLoad so it can be subclassed. Something like:
public class Loader {
private ItemsToLoad Items { get; set; }
protected virtual ItemsToLoad CreateItemsToLoad() {
return new ItemsToLoad();
}
protected class ItemsToLoad {
public virtual void Add() {
}
}
}
public class MyOtherLoader : Loader {
protected override ItemsToLoad CreateItemsToLoad() {
return new MyOtherItemsToLoad();
}
private class MyOtherItemsToLoad : ItemsToLoad {
public override void Add() {
}
}
}

Categories

Resources