none
How to do API version with abstract class RRS feed

  • Question

  • i heard one of usage of abstract class is versioning. so i am looking for a good example which show me how abstract class help in versioning. thanks
    Monday, May 14, 2018 1:56 PM

Answers

  • You really need to put that into context because taken out of context it wouldn't make sense. In general when you are talking about using abstract classes then it is done in comparison to interfaces. Both approaches allow you to abstract away implementation details from the calling code. But when it comes to making changes down the road (aka versioning) then they behave differently.

    With an interface, any changes to the interface will break existing code irrelevant of whether the code needs that functionality or not. That means the interface cannot really grow over time. The general solution has been to create versioned interfaces (e.g.e IMyInterface, IMyInterface2, IMyInterface3). This was very common in the COM world but not so much in .NET.

    //Original version
    public interface IMyInterface
    {
       void Foo ();
    }
    
    //Later version
    public interface IMyInterface
    {
       void Foo ();
    
       //This is a breaking change to the interface
       void Bar ();
    }
    
    //Alternative approach that is not a breaking change
    public interface IMyInterface2 : IMyInterface
    {
       //Not a breaking change but code has to update to use v2
       void Bar();
    }

    With an abstract class you can add new members without breaking any existing code. Provided the existing members aren't changed or removed then no recompilation is necessary. Hence abstract classes are easier to extend over time compared to interfaces.

    //Original version
    public abstract class MyInterface
    {
       public void Foo () { }
    }
    
    //Later version
    public abstract class MyInterface
    {
       public void Foo () { }
    
       //Not a breaking change
       public void Bar () { }
    }
    As with all things though it could be a breaking change if you made it abstract or otherwise required that implementations do something with the new method. But careful design would mitigate this.


    Michael Taylor http://www.michaeltaylorp3.net

    • Proposed as answer by Fei HuModerator Tuesday, May 15, 2018 5:33 AM
    • Marked as answer by Sudip_inn Thursday, May 17, 2018 9:01 AM
    Monday, May 14, 2018 2:06 PM
    Moderator
  • Hello Sudip_inn,

    Could you give me more detailed info with "versioning" because I think we are talking about the different things. Abstract class and interface are often used in design pattern for building flexible, extendable program. For example, structure pattern could care relationship between classes.

    The Below is a simple example that use abstract class.

    An abstract class whose instance method invoke abstract method.

    abstract class MyClass
        {
            public abstract void Test();
    
            public void Start()
            {
                Test();
            }
        }

    And the two subclass mean that different implement with different version.

    class SubClass1 : MyClass
        {
            public override void Test()
            {
                Console.WriteLine("subClass1");
            }
        }
    
        class SubClass2 : MyClass
        {
            public override void Test()
            {
                Console.WriteLine("subClass2");
            }
        }

    Invoke the different version by below code.

    class Program
        {
            static void Main(string[] args)
            {
                start(new SubClass1());
                start(new SubClass2());
            }
    
            static void start(MyClass myClass) {
                myClass.Start();
            }
        }

    The output is:

    subClass1

    subClass2

    Best Regards,

    Neil Hu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, May 15, 2018 6:05 AM
    Moderator

All replies

  • You really need to put that into context because taken out of context it wouldn't make sense. In general when you are talking about using abstract classes then it is done in comparison to interfaces. Both approaches allow you to abstract away implementation details from the calling code. But when it comes to making changes down the road (aka versioning) then they behave differently.

    With an interface, any changes to the interface will break existing code irrelevant of whether the code needs that functionality or not. That means the interface cannot really grow over time. The general solution has been to create versioned interfaces (e.g.e IMyInterface, IMyInterface2, IMyInterface3). This was very common in the COM world but not so much in .NET.

    //Original version
    public interface IMyInterface
    {
       void Foo ();
    }
    
    //Later version
    public interface IMyInterface
    {
       void Foo ();
    
       //This is a breaking change to the interface
       void Bar ();
    }
    
    //Alternative approach that is not a breaking change
    public interface IMyInterface2 : IMyInterface
    {
       //Not a breaking change but code has to update to use v2
       void Bar();
    }

    With an abstract class you can add new members without breaking any existing code. Provided the existing members aren't changed or removed then no recompilation is necessary. Hence abstract classes are easier to extend over time compared to interfaces.

    //Original version
    public abstract class MyInterface
    {
       public void Foo () { }
    }
    
    //Later version
    public abstract class MyInterface
    {
       public void Foo () { }
    
       //Not a breaking change
       public void Bar () { }
    }
    As with all things though it could be a breaking change if you made it abstract or otherwise required that implementations do something with the new method. But careful design would mitigate this.


    Michael Taylor http://www.michaeltaylorp3.net

    • Proposed as answer by Fei HuModerator Tuesday, May 15, 2018 5:33 AM
    • Marked as answer by Sudip_inn Thursday, May 17, 2018 9:01 AM
    Monday, May 14, 2018 2:06 PM
    Moderator
  • An abstract class has nothing to do with versioning. I don't know where you came up with it.  Other classes are derived from a abstract class, which is one of the object oriented programming principles of inheritance.    

    The code shows a classic example of an abstract class being used as a base class, the base controller, that all controllers derive from in the solution,  the bass controller, and they use the base controller's functionality in global exception handlining.

    using System;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Routing;
    using log4net;
    
    namespace MVC.Controllers
    {
        public abstract partial class BaseController : Controller
        {
            private ILog _logger;
    
            protected BaseController()
            {
                _logger =  LogManager.GetLogger(typeof(BaseController));
            }
    
            protected override void OnException(ExceptionContext filterContext)
            {
                AppException appException = new AppException(Convert.ToString(filterContext.Exception))
                {
                    Type = filterContext.GetType().ToString(),
                    StackTrace = filterContext.Exception.StackTrace,
                    Source = filterContext.Exception.Source,
                    InnerException = Convert.ToString(filterContext.Exception.InnerException)
                };
    
                _logger.Error(appException.ToString());
    
                Server.ClearError();
    
                RedirectToControllers("Home", "Error");
            }
    
            private void RedirectToControllers(string control, string action)
            {
                var routeData = new RouteData();
    
                routeData.Values["controller"] = control;
    
                routeData.Values["action"] = action;
    
                IController controller = new HomeController();
    
                ((IController) controller).Execute(new RequestContext(
                    new HttpContextWrapper(System.Web.HttpContext.Current), routeData));
            }
        }
    }
    
    ------------------------------------------------
    
    using System.Web.Mvc;
    using MVC.Models;
    
    namespace MVC.Controllers
    {
        [Authorize]
        public class StudentsController : BaseController  
        {
            private IStudentModels studmods;
            public StudentsController(IStudentModels studentModels)
            {
                studmods = studentModels;
            }
    
            // GET: Students
    
            [AllowAnonymous]
            public ActionResult Index()
            {
                return View(studmods.GetStudents());
            }
    
            //[AllowAnonymous]
            public ActionResult Details(int id = 0)
            {
                return id == 0 ? null : View(studmods.GetStudentById(id));
            }
            public ActionResult Create()
            {
                return View(studmods.Create());
            }
    
            [HttpPost]
            public ActionResult Create(StudentViewModels.Student student)
            {
                if (ModelState.IsValid)
                {
                    studmods.Create(student);
                    return RedirectToAction("Index");
                }
    
                return View(student);
            }
    
            public ActionResult Edit(int id = 0)
            {
                return id == 0 ? null : View(studmods.Edit(id));
            }
    
            [HttpPost]
            public ActionResult Edit(StudentViewModels.Student student)
            {
                if (ModelState.IsValid)
                {
                    studmods.Edit(student);
                    return RedirectToAction("Index");
                }
    
                return View(student);
            }
            public ActionResult Delete(int id = 0 )
            {
                if (id > 0) studmods.Delete(id);
                
                return RedirectToAction("Index");
             }
        }
    }

    Monday, May 14, 2018 3:45 PM
  • Hello Sudip_inn,

    Could you give me more detailed info with "versioning" because I think we are talking about the different things. Abstract class and interface are often used in design pattern for building flexible, extendable program. For example, structure pattern could care relationship between classes.

    The Below is a simple example that use abstract class.

    An abstract class whose instance method invoke abstract method.

    abstract class MyClass
        {
            public abstract void Test();
    
            public void Start()
            {
                Test();
            }
        }

    And the two subclass mean that different implement with different version.

    class SubClass1 : MyClass
        {
            public override void Test()
            {
                Console.WriteLine("subClass1");
            }
        }
    
        class SubClass2 : MyClass
        {
            public override void Test()
            {
                Console.WriteLine("subClass2");
            }
        }

    Invoke the different version by below code.

    class Program
        {
            static void Main(string[] args)
            {
                start(new SubClass1());
                start(new SubClass2());
            }
    
            static void start(MyClass myClass) {
                myClass.Start();
            }
        }

    The output is:

    subClass1

    subClass2

    Best Regards,

    Neil Hu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, May 15, 2018 6:05 AM
    Moderator
  • how the above asp.net related code shows the versioning concept implemented with abstract class.

    thanks

    Tuesday, May 15, 2018 9:39 AM
  • how the above asp.net related code shows the versioning concept implemented with abstract class.

    thanks

    It doesn't show anything about versioning, but rather, it shows the basic concepts of OO and  inheritance as all derived classes from the base class inherit the base class's functionality.

    That's it no more and no less on what the code shows. 

    What you are trying to come up with about some versioning using an abstract class would be something I would never try to implement. 

    Tuesday, May 15, 2018 12:00 PM