I'm having a problem designing part of my program (not writing it, for once!). This is kind of hard to explain without writing a novel, so I'll try and be brief.
Basically, I have a program which reads/writes parameters from a piece of hardware. Currently, it does so over Serial, but eventually, I'll like it to do so over USB, using the .NET wrapper for the FTDI chip http://www.ftdichip.com/Projects/CodeExamples/CSharp.htm
I think my problem is, I know I want several layers of abstraction, but I can't seem to know where to draw the lines. First, I don't want my ReadParam(), WriteParam(), and SendCommand() functions to be sitting in my main form class. That just seems cobbled. So obviously they should be in some other class, which I'll instantiate. Let's call that Comm for now.
The first option is, I could make an interface, lets say IComm, and have my Serial and USB flavors both implement that. The problem with this is, a large percentage of the code would be duplicated in both flavors, because I have special ReadReplyData() and other functions, that do pre-processing of the serial data before they return it to the GUI.
So the next option, is have Comm be an intermediary class, which defines an interface ICommDriver. Comm would implement a private ReadReplyData() formatting function, as well as the public ReadParam(), WriteParam(), and SendCommand() functions, while ICommDriver would specify only simpler Read and Write functions.
This all seems trivial except for two twists. One, I want this to be multi-theaded, obviously, so the GUI doesn't hang. So I'm thinking that Comm would use a BackgroundWorker to do all the reads/writes. Also, the Serial flavor needs to be told which COM port to open (from a GUI drop-down), while the USB flavor does not. So do I make that part of the interface or not?
Thanks for your help everyone, I've been writing/deleting code for days trying to figure out the correct way to do this!
Jonathon
I know I want several layers of
abstraction, but I can't seem to know
where to draw the lines
This is where your problem lies. It is a fundamentally flawed approach to development and it is exactly what leads to this paralysis. Develop several concrete implementations of the flavors first. Get them working in your application with kludgy if type1 else type2 logic. Then go back and refactor them all to share a common contract, common base, what have you. It will be blindingly obvious what needs to go where.
With more details in the comments:
If you have shared code between implementations, you should use an abstract class. In my experience it's best practice to keep the public methods final and call protected abstract methods from the public methods, like so:
public interface IComm
{
void WriteParam(...);
}
public abstract class CommStandardBase : IComm
{
public void WriteParam(...)
{
DoWriteParam(...);
}
private void DoWriteParam(...)
{
CommonWrite1(...);
HandleWriteParam(...);
CommonWrite2(...);
}
protected abstract void HandleWriteParam(...);
private void CommonWrite1(...)
{
...
}
private void CommonWrite2(...)
{
...
}
}
Make each class self-contained. It should be single-instance, single-threaded and can be passed between workers and reporters.
In regards to exactly which kind of interfaces you need, that is ultimately up to you and whoever knows how this application works at that low of a level. I would like to respond to the part about using your implementations in a UI, and the comment about Comm using a BackgroundWorker. I would recommend inverting that. BackgroundWorker is really a UI level component....but Comm would be more of a "central" component (like a business object in an enterprise application). Your UI should create a BackgroundWorker that then creates Comm instances to perform the required work, and orchestrate any events from your Comm to update the UI. If you need your UI and the BackgroundWorker to communicate over a lengthy duration of time, I would recommend creating some kind of data transfer object that your UI can create, drop in a queue, and use ManualResetEvent or AutoResetEvent threading handles to communicate between your UI thread and the BackgroundWorker. That should give you a more loosely coupled product, allowing you to develop your Comm class independantly of any kind of UI that may display it (possibly allowing you to have WindForms, WPF, Command line, and maybe even PowerShell clients.)
I am somewhat in VB.NET mode at the momement so here goes...
Interface IComm
Function ReadParam()
Function WriteParam()
Function SendCommand()
End Interface
>
MustInherit Class CommBase
.... Load this up with the overideable
End Class
Then just implement the interface and inherit the base if needed. I also agree with Rex M. Don't push it too far for loose coupling.
Related
I have looked at other discussions about this topic (on StackOverflow) however the other questions seem to be language specific whereas this is not language specific and I'm considering no longer using private methods, classes, and modules.
I want to test my private methods, classes, and modules so that I can more easily locate bugs. To allow me to do this I'm considering no longer using private methods, classes, and modules for two reasons, (1) I see no reasonable way of testing a private method, class, or module without injecting test code or using some sort of "magic" and (2) to improve code reuse. Note that I'm not considering no longer using private variables and properties because data needs protecting and does not provide behaviour therefore it does not need to be public during testing.
As a lame example, if you're writing a module called OneOperations that has two public methods addOne and subtractOne, and two private methods add and subtract. If you were not allowing yourself to have private methods you would put the two private methods into another module (basicOperations) where they are public and import those methods inside the OneOperations module. From this you should now be able to write testing code for all the methods in both modules without injecting code. An advantage of this is that the methods add and subtract can now be used in other modules by importing the basicOperations module (2 - improving code reuse).
I have a feeling this a bad idea, but I lack the real world experience to justify not doing this, which is why I've posted this question on StackOverflow.
So, how do you test your private methods, classes, and modules? Is not writing private methods, modules, and classes a potential solution?
1) Like in many other answers on this topic, the main question is why would you want to test your private methods? The purpose of a class is to provide some functionality to its clients. If you have comprehensive unit tests that prove that the public interface of this class behaves correctly, why do you care what it's doing in its private methods?
2) Your idea of not having private methods at all seems like cutting your leg off. For small projects it may be possible to have every tiny behaviour well separated and tested. But for large projects it's an overkill. What matters, is the domain logic behaving correctly.
Consider for example a method:
public double getDistanceSquared(Point other)
{
return getDifferenceSquared(this.x, other.x)
+ getDifferenceSquared(this.y, other.y);
}
private double getDifferenceSquared(double v1, double v2)
{
return (v1 - v2)*(v1 - v2);
}
Ad1) Does it really make sense to unit test getDifferenceSquared method, if getDistanceSquared returns correct results for all test cases?
Ad2) Creating a separate class for calculating squared distance between doubles - in case there is only one place when it'll be used leads to a swarm of tiny classes, with millions of tests. Also, constructors of your domain classes will accept like 10 different interfaces for every tiny thing they're doing internally.
Maintaining all this is a lot of unnecessary work. Imagine that you would like to change the method of calculating the distance (maybe use some precomputed values). The behaviour of getDistanceSquared would not change. But you would have to change all of the tests of getDifferenceSquared even though you shouldn't have to care how is the distance being calculated, as long as it's calculated correctly.
Diving into minor details when it's not necessary makes you forgot what you're really doing - you lose the "big picture view". Value your time, and focus on important problems.
As a side note, also - the main concern of unit tests is not "locating bugs" as you suggest. They impose a clean design, provide an always up-to-date documentation of your code's behaviour and allow convenient refactoring giving you flexibility. Additionally they assure you that the code is working as you expect it to.
http://artofunittesting.com/definition-of-a-unit-test/
http://en.wikipedia.org/wiki/Unit_testing#Benefits
There is another way to look at this, which is how do you generate a private method?
If we are following the TDD process properly, then the first thing we write is the test. At this point the test should contain all of our code, e.g.
public void ShouldAddTwoNumbers()
{
(1 + 1).ShouldEqual(2);
}
Yes, that looks appalling. But consider what happens as we write is some more tests.
public void ShouldAddTwoMoreNumbers()
{
(2 + 2).ShouldEqual(4);
}
Now we have something to reactor, so it can become
public void ShouldAddTwoNumbers()
{
Add(1, 1).ShouldEqual(2);
}
public void ShouldAddTwoMoreNumbers()
{
Add(2, 2).ShouldEqual(4);
}
private int Add(int a, int b)
{
return a+b;
}
So now we have a private method that we can test inside our test class. It's only when you complete further refactoring to move the code out into your application, that the private becomes an issue. Most automated refactoring tools will offer you the option of changing the methods signature at this point, so that the private method is still accessible, because its not private.
(There is a fabulous exercise called TDD as if you mean it by Keith Braithwaite which I've just paraphrased above)
However, this isn't the end of our refactorings and development. One thing that we should be doing as we write and refactor our tests is to delete old tests, for example when functionality is duplicated. Another is to extract new methods so we don't repeat ourselves. Both of these can lead to scenarios where we have private methods back in the non-test code base.
So my advice is to be pragmatic, make the best decision you can for the code that you have in front of you. I wouldn't advise not creating private methods, but I would instead look at the factors that lead you to create them.
I have inherited a project that has no interfaces or abstract classes i.e. concrete classes only and I want to introduce unit testing. The classes contain lots of functions, which contain business logic and data logic; breaking every rule of SOLID (http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29).
I had a thought. I was thinking about creating interfaces for each of the poorly designed classes, exposing all functions. Then at least I can Mock the classes.
I am relatively new to Unit Testing (I have experience with a project, which was very well developed using interfaces in the right places). Is it a good idea to do this i.e. create interfaces for all the concrete classes (exposing all the functions and sub routines), just for unit testing?
I have spent some time researching this but I have not found an answer.
If your project has no tests at all, before adding any unit tests I'd much rather create higher level tests (i.e acceptance, functional and/or integration tests).
When you have those tests in place you know that the system is behaving as it should and also that it has certain level of 'external' quality (meaning by this that the inputs and outputs of your program are the expected ones).
Once your high level tests are working, you could try to add unit tests to the classes that already exist.
I bet that you will find yourself in the need to refactor some of the existing classes if you want to be able to unit test them so you can use your high level tests as a safety net that will tell you if you've broken anything.
This is a tough thing to tackle. I think you are on the right track. You'll end up with some ugly code (such as creating header interfaces for each monolithic class), but that should just be an intermediate step.
I'd suggest investing in a copy of Working Effectively with Legacy Code. First you could start by reading this distillation.
In addition to Karl's options (which let you mock via interception), you could also use Microsoft Fakes & Stubs. But these tools will not encourage you to refactor the code to adhere to SOLID principles.
Yes, that is a good start, however, having interfaces is less of a priority than having dependencies injected. If all of your legacy classes gain interfaces, but hidden internally they are still all interdependent, the classes will still be no easier to test. For instance, let's say you had two classes that looked like this:
Public Class LegacyDataAccess
Public Function GetAllSales() As List(Of SaleDto)
' Do work with takes a long time to run against real DB
End Function
End Class
Public Class LegacyBusiness
Public Function GetTotalSales() As Integer
Dim dataAccess As New LegacyDataAccess()
Dim sales As List(Of SaleDto) = dataAccess.GetAllSales()
' Calculate total sales
End Function
End Class
I know what you're already saying... "I wish the legacy code was at least layered that well", but lets use that as an example of some legacy code which would be hard to test. The reason it's hard to test is because the code reaches out to the database and executes a time-consuming query on the database and then calculates the results from that. So, in order to test it in its current state, you would need to first write out a bunch of test data to the database, then run the code to see if it returns the correct results based on that inserted data. Having to write a test like that is problematic because:
It is a pain to write the code to setup the test
The test will be brittle because it depends on the outside database working properly and on it containing all the correct supporting data
The test will take too long to run
As you correctly observe, interfaces are very important to unit testing. So, as you recommend, lets add interfaces to see if it makes it any easier to test:
Public Interface ILegacyDataAccess
Function GetAllSales() As List(Of SaleDto)
End Interface
Public Interface ILegacyBusiness
Function GetTotalSales() As Integer
End Interface
Public Class LegacyDataAccess
Implements ILegacyDataAccess
Public Function GetAllSales() As List(Of SaleDto) _
Implements ILegacyDataAccess.GetAllSales
' Do work with takes a long time to run against real DB
End Function
End Class
Public Class LegacyBusiness
Implements ILegacyBusiness
Public Function GetTotalSales() As Integer _
Implements ILegacyBusiness.GetTotalSales
Dim dataAccess As New LegacyDataAccess()
Dim sales As List(Of SaleDto) = dataAccess.GetAllSales()
' Calculate total sales
End Function
End Class
So now we have the interfaces, but really, how does that make it any easier to test? Now we can easily create a mock data access object, which implements the same interface, but that's not really the core problem. The problem is, how do we get the business object to use that mock data access object instead of the real one? To do that, you need to take your refactoring to the next level by introducing dependency-injection. The real culprit is the New keyword in the following line of the business class:
Dim dataAccess As New LegacyDataAccess()
The business class clearly depends on the data access class, but currently it is hiding that fact. It's lying about it's dependencies. It's saying, come-on, it's easy, just call this method and I'll return the result--that's all it takes. When really, it takes a lot more than that. Now, let's say we stopped it from lying about it's dependencies and made it so it unabashedly stated them, like this:
Public Class LegacyBusiness
Implements ILegacyBusiness
Public Sub New(dataAccess As ILegacyDataAccess)
_dataAccess = dataAccess
End Sub
Private _dataAccess As ILegacyDataAccess
Public Function GetTotalSales() As Integer _
Implements ILegacyBusiness.GetTotalSales
Dim sales As List(Of SaleDto) = _dataAccess.GetAllSales()
' Calculate total sales
End Function
End Class
Now, as you can see, this class is much easier to test. Not only can we easily create a mock data access object, but now we can easily inject the mock data access object into the business object. Now we can create a mock which quickly and easily returns exactly the data we want it to return and then see if the business class returns the correct calculation--no database involved.
Unfortunately, while adding interfaces to existing classes is a breeze, refactoring them to use dependency-injection typically requires a lot more work. You will likely need to plan out which classes make the most sense to tackle first. You may need to create some intermediary old-school wrappers which work the way the code used to, so you don't break existing code while you are in the process of refactoring the code. It's not a quick and easy thing, but if you are patient and in it for the long-haul, it is possible to do it, and you will be glad you did.
I would recommend you go the interface route, but if you want to pay for a solution, then try one of these:
TypeMock
JustMock
Creating interfaces to test the classes is not a bad idea - the goal of unit testing is to exercise if the functions on a class are functioning as expected. Depending on the classes you are working with, this could be easier said than done - if there are a lot of dependencies on global states, etc. you will need to mock accordingly.
Given how valuable unit tests are, putting a bit of work into them (to a limit) will benefit you and developers you work with.
I prefer to create interfaces and classes as you need to test things and not all upfront.
Besides interfaces, you can use some techniques to test legacy code. The one I often use is "Extract And Override", where you extract some piece off "untestable" code inside other method and make it overridable. Them derive the class that you want to test and override the "untestable" method with some sensing code.
Using a mock framework will be as easy as adding keyword Overridable to the method and sets the returning using the mock framework.
You can find many techniques on the book "Working Effectively with Legacy Code".
One thing about existing code, is that sometimes it is better to write integration tests than unit tests. And after you have the behavior under test, you create unit tests.
Another tip is to start with modules/class that have less dependencies, that way, you become familiar with the code with less pain.
Let me know if you need an example about "extract and override" ;)
I'm not so sure the title is a good match for this question I want to put on the table.
I'm planning to create a web MVC framework as my graduation dissertation and in a previous conversation with my advisor trying to define some achivements, he convinced me that I should choose a modular design in this project.
I already had some things developed by then and stopped for a while to analyze how much modular it would be and I couldn't really do it because I don't know the real meaning of "modular".
Some things are not very cleary for me, like for example, just referencing another module blows up the modularity of my system?
Let's say I have a Database Access module and it OPTIONALY can use a Cache module for storing results of complex queries. As anyone can see, I at least will have a naming dependency for the cache module.
In my conception of "modular design", I can distribute each component separately and make it interact with others developed by other people. In this case I showed, if someone wants to use my Database Access module, they will have to take the Cache as well, even if he will not use it, just for referencing/naming purposes.
And so, I was wondering if this is really a modular design yet.
I came up with an alternative that is something like creating each component singly, without don't even knowing about the existance of other components that are not absolutely required for its functioning. To extend functionalities, I could create some structure based on Decorators and Adapters.
To clarify things a little bit, here is an example (in PHP):
Before
interface Cache {
public function isValid();
public function setValue();
public function getValue();
}
interface CacheManager {
public function get($name);
public function put($name, $value);
}
// Some concrete implementations...
interface DbAccessInterface {
public doComplexOperation();
}
class DbAccess implements DbAccessInterface {
private $cacheManager;
public function __construct(..., CacheManager $cacheManager = null) {
// ...
$this->cacheManager = $cacheManager;
}
public function doComplexOperation() {
if ($this->cacheManager !== null) {
// return from cache if valid
}
// complex operation
}
}
After
interface Cache {
public function isValid();
public function setValue();
public function getValue();
}
interface CacheManager {
public function get($name);
public function put($name, $value);
}
// Some concrete implementations...
interface DbAccessInterface {
public function doComplexOperation();
}
class DbAccess implements DbAccessInterface {
public function __construct(...) {
// ...
}
public function doComplexQuery() {
// complex operation
}
}
// And now the integration module
class CachedDbAcess implements DbAccessInterface {
private $dbAccess;
private $cacheManager;
public function __construct(DbAccessInterface $dbAccess, CacheManager $cacheManager) {
$this->dbAccess = $dbAccess;
$this->cacheManager = $cacheManager;
}
public function doComplexOperation() {
$cache = $this->cacheManager->get("Foo")
if($cache->isValid()) {
return $cache->getValue();
}
// Do complex operation...
}
}
Now my question is:
Is this the best solution? I should do this for all the modules that do not have as a requirement work together, but can be more efficient doing so?
Anyone would do it in a different way?
I have some more further questions involving this, but I don't know if this is an acceptable question for stackoverflow.
P.S.: English is not my first language, maybe some parts can get a little bit confuse
Some resources (not theoretical):
Nuclex Plugin Architecture
Python Plugin Application
C++ Plugin Architecture (Use NoScript on that side, they have some weird login policies)
Other SO threads (design pattern for plugins in php)
Django Middleware concept
Just referencing another module blows up the modularity of my system?
Not necessarily. It's a dependency. Having a dependencies is perfectly normal. Without dependencies modules can't interact with each other (unless you're doing such interaction indirectly which in general is a bad practice since it hides dependencies and complicates the code). Modular desing implies managing of dependencies, not removing them.
One tool - is using interfaces. Referencing module via interface makes a so called soft dependency. Such module can accept any implementation of an interface as a dependency so it is more independant and as a result - more maintainable.
The other tool - designing modules (and their interfaces) that have only single responcibility. This also makes them more granular, independant and maintainable.
But there is a line which you should not cross - blindly applying these tools may leed to a too modular and too generic desing. Making things too granular makes the whole system more complex. You should not solve universe problems, making generic modules, that all developers can use (unless it is your goal). First of all your system should solve your domain tasks and make things generic enough, but not more than that.
I came up with an alternative that is something like creating each component singly, without don't even knowing about the existance of other components that are not absolutely required for its functioning
It is great if you came up with this idea by yourself. The statement itself, is a key to modular programming.
Plugin architecture is the best in terms of extensibility, but imho it is hard to maintenance especially in intra application. And depending the complexity of plugin architecture, it can make your code more complex by adding plugin logics, etc.
Thus, for intra modular design, I choose the N-Tier, interface based architecture. Basically, the architecture relays on those tiers:
Domain / Entity
Interface [Depend on 1]
Services [Depend on 1 and 2]
Repository / DAL [Depend on 1 and 2]
Presentation Layer [Depend on 1,2,3,4]
Unfortunately, I don't think this is achieveable neatly in php projects as it need separated project / dll references in each tier. However, following the architecture can help to modularize the application.
For each modules, we need to do interface-based design. It can help to enhance the modularity of your code, because you can change the implementation later, but still keep the consumer the same.
I have provided an answer similiar to this interface-based design, at this stackoverflow question.
Lastly but not least, if you want to make your application modular to the UI, you can do Service Oriented Architecture. This is simply make your application as bunch of services, and then make the UI to consume the service. This design can help to separate your UI with your logic. You can later use different UI such as desktop app, but still use the same logic. Unfortunately, I don't have any reliable source for SOA.
EDIT:
I misunderstood the question. This is my point of view about modular framework. Unfortunately, I don't know much about Zend so I will give examples in C#:
It consist of modules, from the smallest to larger modules. Example in C# is you can using the Windows Form (larger) at your application, and also the Graphic (smaller) class to draw custom shapes in the screen.
It is extensible, or replaceable without making change to base class. In C# you can assign FormLoad event (extensible) to the Form class, inherit the Form or List class (extensible) or overridding form draw method to create a custom window graphic (replaceable).
(optional) it is easy to use. In normal DI interface design, we usually inject smaller modules into a larger (high level) module. This will require an IOC container. Refer to my question for detail.
Easy to configure, and does not involve any magical logic such as Service Locator Pattern. Search Service Locator is an Anti Pattern in google.
I don't know much about Zend, however I guess that the modularity in Zend can means that it can be extended without changing the core (replacing the code) inside framework.
If you said that:
if someone wants to use my Database Access module, they will have to take the Cache as well, even if he will not use it, just for referencing/naming purposes.
Then it is not modular. It is integrated, means that your Database Access module will not work without Cache. In reference of C# components, it choose to provide List<T> and BindingList<T> to provide different functionality. In your case, imho it is better to provide CachedDataAccess and DataAccess.
So as I've been reading/learning about classes and the methods within them I've found very little about the practical differences between declaring a method as public versus private.
I know that the difference is a private class can only be accessed within the class, while a public method can be accessed from code outside the class (other classes, functions). But what I really want to know is:
Why would you want/not want to declare it one way or another when deploying an application?
Are there best practices that can guide whether to declare a method public vs private?
Also, I don't know if it matters, but I am learning primarily VB.Net and C# in a web application environment, so specifics to that would help.
Encapsulation means that you should think of each class as a machine that provides a service. For example, a chair allows you to sit on it, or a lawnmower allows you to cut your lawn.
The private methods pertain to the machine's internal workings. In contrast, the public methods relate to how you (other classes) interact with the machine.
Example one: Chair...
When sitting on a chair, you don't need to know volume of stuffing or the number of staples, you basically need to know whether or not it's occupied and if it's stable.
Public methods: IsStable, IsOccupied, Sit
Private methods: CalculateStuffingVolume, CountNumberOfStaples
Example two: Lawnmower...
For the lawnmower, you need to know if it has enough fuel (or is plugged in), if the blades are sharp, and be able to turn it on.
Public methods: GetFuelLevel, IsBladesSharp, TurnOn, TurnOff
Private methods: Combust, etc, Too many to imagine.
Conclusion:
So when you're developing all you will see is...
Example one: Chair.Sit, Chair.IsStable and Chair.IsOccupied
or
Example two: Lawnmower.GetFuelLevel, Lawnmower.IsBladesSharp, Lawnmower.TurnOn, LawnMower.TurnOff
As a developer, you will not have to think about number of threads in the uphosltry, the colour of the fuel cap, the number of RPM of the blades or whether the chair is glued or stapled together. This distinction makes it much easier to put your application together without being swamped in detail. Additionally, it allows programmers to expose only necessary information which adds a level of security. As John mentioned, this prevents the Person class from calling Lawnmower.Combust(fuel) when they're not supposed to.
If the method is private, then you don't have to think about outside classes calling it incorrectly.
One of the benefits of this is that it allows for a separation between the interface to your class (the public parts of it), and the implementation of it. If nobody knows how you implemented your class (that is, if there is no code that depends on how you implemented it), then you're free to change the way you implemented it without breaking any other code.
It's one of the most importand principles of the object-oriented programming -- encapsulation.
A class usually provides a (public) interface. E.g. (pseudocode):
class Rectangle {
private length;
private width;
public getPerimeter() {
// return calculatePerimeterOld();
return calculatePerimeterNew();
}
private calculatePerimeterOld() {
// old variant
}
private calculatePerimeterNew() {
// Here the perimeter is caltulated.
// so: perimeter = 2 * (length + width)
// or so: perimeter = 2 * (length) + 2 * (width)
// or maybe so: perimeter = length + width + length + width - (0.5 * length) + 2 * 0.25 * length)
return perimeter;
}
}
I can change my private methods however I want. I can rename or replace them with oher methods. But my public interface will stay the same -- and it has to stay the same, because it's a contract I sign, when I'm defining a mehod as public. Everything, what is signed as private is my "blackbox" and I can do there whatever I want.
It's the main reason. Another reason is, that we should not provide the user(-s) of our class with methods/informations, they don't need. To much (information) is not good.
If you're developing a one off website maintained just by you, you may find the concept of public and private functions unnecessary.
However, if you're delivering software to other people, and they're building on top of your software, it is an absolutely critical concept.
Think of it like a physical machine that has a thousand knobs and switches inside it, but is contained inside a pretty case with only a few clearly labelled knobs on the outside.
The public functions and methods are the ones you create for external parties to interact with your software.
The private functions and methods are the ones you create for your software to interact with
itself.
But, again, if it's a one-off website maintained by a single developer, these differences are less important.
I am going over some OO basics and trying to understand why is there a use of Interface reference variables.
When I create an interface:
public interface IWorker
{
int HoneySum { get; }
void getHoney();
}
and have a class implement it:
public class Worker : Bee, IWorker
{
int honeySum = 15;
public int HoneySum { get { return honeySum; } }
public void getHoney()
{
Console.WriteLine("Worker Bee: I have this much honey: {0}", HoneySum);
}
}
why do people use:
IWorker worker = new Worker();
worker.getHoney();
instead of just using:
Worker worker3 = new Worker();
worker3.getHoney();
whats the point of a interface reference variable when you can just instatiate the class and use it's methods and fields that way?
If your code knows what class will be used, you are right, there is no point in having an interface type variable. Just like in your example. That code knows that the class that will be instantiated is Worker, because that code won't magically change and instantiate anything else than Worker. In that sense, your code is coupled with the definition and use of Worker.
But you might want to write some code that works without knowing the class type. Take for example the following method:
public void stopWorker(IWorker worker) {
worker.stop(); // Assuming IWorker has a stop() method
}
That method doesn't care about the specific class. It would handle anything that implements IWorker.
That is code you don't have to change if you want later to use a different IWorker implementation.
It's all about low coupling between your pieces of code. It's all about maintainability.
Basically it's considered good programming practice to use the interface as the type. This allows different implementations of the interface to be used without effecting the code. I.e. if the object being assigned was passed in then you can pass in anything that implements the interface without effecting the class. However if you use the concrete class then you can only passin objects of that type.
There is a programming principle I cannot remember the name of at this time that applies to this.
You want to keep it as generic as possible without tying to specific implementation.
Interfaces are used to achieve loose coupling between system components. You're not restricting your system to the specific concrete IWorker instance. Instead, you're allowing the consumer to specify which concrete implementation of IWorker they'd like to use. What you get out of it is loosely dependent components and better flexibility.
One major reason is to provide compatibility with existing code. If you have existing code that knows how to manipulate objects via some particular interface, you can instantly make your new code compatible with that existing code by implementing that interface.
This kind of capability becomes particularly important for long-term maintenance. You already have an existing framework, and you typically want to minimize changes to other code to fit your new code into the framework. At least in the ideal case, you do this by writing your new code to implement some number of existing interfaces. As soon as you do, the existing code that knows how to manipulate objects via those interfaces can automatically work with your new class just as well as it could with the ones for which it was originally designed.
Think about interfaces as protocols and not classes i.e. does this object implement this protocol as distinct from being a protocol? For example can my number object be serialisable? Its class is a number but it might implement an interface that describes generally how it can be serialised.
A given class of object may actually implement many interfaces.