Author Topic: arrays  (Read 10302 times)

0 Members and 1 Guest are viewing this topic.

JohnK

  • Administrator
  • Seagull
  • Posts: 10625
Re: arrays
« Reply #30 on: July 31, 2014, 06:06:37 AM »
If I may stray off topic a tad for a sec, it's still relevant in most respects though (to people new to C#/.net).

Hi John,
Inheritance and polymorphism is over emphasised in learning literature IMO, when learning it's very easy to get caught up inheriting from everything to keep things DRY, this is bad as it creates very tightly coupled code that makes your libraries almost useless for any other applications. If you are trying to write unit/integration tests for existing code you will quickly learn why inheritance can be overused very easily.

The less talked about paradigm is Interfaces, these are what make things like the 'foreach' statement very powerful. By using the ICollection interface and overriding the necessary methods you can create your own collection types that can be iterated using foreach.

It's taken me a while but I've finally got my head around unit testing and it was interfaces that provided the 'aha!' moment, by creating your own interfaces you are creating an api that you can then plug your inherited classes into as dependencies. Test driven development pretty much enforces this style of architecture and well worth investigating once you get the language basic down.

Windows .Net loves you to inherit from their classes as it ties you tightly to the technology, I don't think this was deliberate but it does make things easy when creating user controls etc. By using interfaces though you can then separate the internal logic of your custom control behavior from the api and reuse it in other platforms (think gaming or web tech).

Check out some vid's/books from Robert C. Martin (Uncle Bob) on S.O.L.I.D design, well worth a look.

Hi ya Mick.
No kidding? I just got done reading a chapter on interfaces and I thought they were the dumbest thing and I told myself I will never use these because of what a PITA (pain in the…) they seemed to be. After that post though, they are defiantly worth the look. I have an idea for an api I want to test ideas out with so I will try interfaces first.

If you have any small-easy-to-chew samples of test driven development methology code I would love to read it. I was just getting into that with C++.

Done, I will check out S.O.L.I.D. I already have his page bookmarked and will start reading it while I drink my morning coffee.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Locke

  • Guest
Re: arrays
« Reply #31 on: July 31, 2014, 11:04:48 AM »
C# in Depth by Jon Skeet is an outstanding read.  Additionally, Marc Gravell and Eric Lippert both have blogs worth following.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: arrays
« Reply #32 on: July 31, 2014, 12:59:22 PM »
John,
to relate a interface to C++ would be a abstract class with all abstract members.


About every example I have seen on Inheritance is so simple that using Inheritance  just makes it more complicated and makes it hard to realize or see the benefits in it. Looking at a popular or successful open source project would probably be a much better example.

Just because something "is a" does not mean it should inherit from that object, and there is usually never that perfect abstraction that some literature tend to imply exists.

Those animal and vehicle examples just make it more confusing and give you a bad context a lot times when thinking about an actual real project.


Inheritance and polymorphism gets tightly coupled with thinking abstractly so it is usually explained with an abstraction, but to look at it for what it is helps me I think if should be used, as in what is actually happening and this is obviously not the exact way it works but thinking of inheritance as

Classes will have there properties(data) and a method table(a table that points to each of its functions defined in class)

When I inherit from class starts of with the class I inherited from and will restrict access to certain methods depending on if private, etc....
I can add new properties(data) and methods to its method table.
If a method is virtual in base class then that allows me to change the method pointed to in method table to the new class implementation.
If method is abstract then I have to provide a method for the method table to point to.
Polymorphism just means sense part of its definition is the base class I can treat it as the base class.
Will this help me or make it easier to deal with?

The main thing about Test driven development I like as Mick mentioned is way it forces you to approach project.
The traditional OOP approach of creating an abstraction I think is almost impossible without many years of experience of creating applications to be able even know how to formulate ones that will actual work and be a benefit to the project.




 
 

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: arrays
« Reply #33 on: July 31, 2014, 04:53:02 PM »

Here's a pretty good Inheritance tree you'll see fairly often.



And the derived Types from Curve;  think " .. Is a curve "



These are a little more practical than the 'typical' car class you'll see in books.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: arrays
« Reply #34 on: July 31, 2014, 06:27:17 PM »
As JeffH was saying, there's definitely a place for inheritance and his example of member data and specific member methods still holds. Interfaces are basically a 'contract' of what an object can do or provide (such as the foreach example), what this means is that you can 'tack' on an interface and pass ANY object type that inherits that interface to a consumer of that api. This has a lot more power than polymorphism.

An interface is like a 'shim' or adapter if you will and that's why you won't see them used so much in sample code as they only confuse the issue.

@John,

I don't have anything that explains the concept at the moment, but I'll try a brief(?) description of the process.

In TDD you create your tests first for class that you want to test, you create these test methods to test your class methods and you will find that some of these methods require other objects.
To inject these dependencies that don't exist yet (you write your tests first remember) you need to create something, here's where you would use an interface.
You would then write a 'helper' or mock class that consumes your new interface and all this class does is help make the tests pass, even with BS code/data, just make it pass. You have now 'inverted' your dependency by letting the interface worry about it instead of your new class being tightly coupled to an actual object.

That sounds counter intuitive at first but you are not testing your dependencies just yet, only that the implementation details of the class you are working on behaves as expected, integration testing is when you plug it all together to test real dependencies all work together.

So, you have tested your new class and you have one or more new interfaces (apis if you will) for your dependencies, you can now create tests for the real dependency classes instead of helpers inheriting the interfaces as the api. Rinse and repeat.
This way you don't end up writing code you don't need as you are designing the api as you go and re-factoring out unused code and keeping it all DRY. It also allows you to change the implementation details without breaking anything, you could even plug in completely different dependencies as long as you implement the interface api.

A good example of this is something like the ActiveRecords or PDO database api's, they have a simple connection method that is used to connect to any db by using an interface to abstract the actual connection details away. You could do this with inheritance but that would means all the different companies would need to agree on the abstract base class and methods they would all need to use. By using an interface you can change the underlying database connection details without breaking all of the legacy code that uses the connection api. This is a good separation of concerns if you will and TDD pretty much enforces you to code this way.

So now you're thinking "that's more than double the code I really need to write my app" and this may be true at the start but remember some important points:
- you only write code you need, you don't go off writing stuff you think you may need but never use
- you change only the implementation details, not the api
- you have a much better and maintainable architecture, the tests serve as excellent documentation as well
- you run your tests continually throughout your dev process catching bugs as you go
- the tests provide an exact location of a problem when a test fails, setting break points and stepping through code is seldom done.
- all of your testing is automated saving you many more hours debugging than it took to write the tests (this is key!)
- you will have the confidence to change things any time you like as any bugs are quickly found and extra new tests may need to be written and the problem easily fixed.

It's a big topic but well worth the effort I think.
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

JohnK

  • Administrator
  • Seagull
  • Posts: 10625
Re: arrays
« Reply #35 on: July 31, 2014, 06:33:43 PM »

I hope you don't mind me giving a C++ more realistic `typical car class' example...

Code - C++: [Select]
  1. // create a base class...
  2. //
  3. class BaseClass
  4. {
  5.     long id;
  6.     std::string description
  7. public:
  8.     // default constructor
  9.     BaseClass() {
  10.         id = 0;
  11.     }
  12.  
  13.     // default destructor
  14.     virtual ~BaseClass () {}
  15.  
  16.     // =---------=
  17.     //  get'rs
  18.     // =---------=
  19.     virtual long get_id() { return id; }
  20.     virtual std::string& get_description() { return description; }
  21.  
  22.     // =---------=
  23.     //  set'rs
  24.     // =---------=
  25.     virtual bool set_id(long n) {
  26.         id = n;
  27.         if (id == n) return true;
  28.         else return false;
  29.     }
  30.     virtual bool set_description(std::string &str) {
  31.         description = str;
  32.         if (description == str) return true;
  33.         else return false;
  34.     }
  35. };
  36.  
  37. // Make some inheritance happen...
  38. //
  39. class DerivedClassOne :public BaseClass
  40. {
  41.     double Value;
  42. public:
  43.     // default constructor
  44.     DerivedClassOne() {
  45.         Value = 0;
  46.     }
  47.  
  48.     // default destructor
  49.     virtual ~DerivedClassOne () {}
  50.  
  51.     // =---------=
  52.     //  get'rs
  53.     // =---------=
  54.     virtual double get_Value() { return Value; }
  55.  
  56.     // =---------=
  57.     //  set'rs
  58.     // =---------=
  59.     virtual bool set_Value(double v) {
  60.         Value = v;
  61.         if (Value == v) return true;
  62.         else return false;
  63.     }
  64. };
  65.  
  66. // Let's make this a little more "real world" and create another
  67. // class...
  68. //
  69. class DerivedClassTwo :public DerivedClassOne
  70. {
  71.     double AnotherValue;
  72. public:
  73.     // default constructor
  74.     DerivedClassTwo() {
  75.         AnotherValue = 0;
  76.     }
  77.  
  78.     // default destructor
  79.     virtual ~DerivedClassTwo () {}
  80.  
  81.     // =---------=
  82.     //  get'rs
  83.     // =---------=
  84.     virtual double get_AnotherValue() { return AnotherValue; }
  85.  
  86.     // =---------=
  87.     //  set'rs
  88.     // =---------=
  89.     virtual bool set_AnotherValue(double v) {
  90.         AnotherValue = v;
  91.         if (AnotherValue == v) return true;
  92.         else return false;
  93.     }
  94. };
  95.  
  96. // So far everything seems neat and tidy (read: linear). Let me
  97. // demonstrate usage now...
  98. //
  99. int main(int argc, char** argv)
  100. {
  101.     DerivedClassTwo *MySuperAwesomeClass = new DerivedClassTwo();
  102.     // create an instance of "DerivedClassTwo" (the last in the
  103.     // inheritance chain) and call it "MySuperAwesomeClass".
  104.     MySuperAwesomeClass.set_id( 7 );
  105.     // Set the ID var in the BaseClass class
  106.  
  107.     std::string mySuperAwesomeClassDescriptionString( "Description String" );
  108.     MySuperAwesomeClass.set_description( mySuperAwesomeClassDescriptionString );
  109.     // Set the description var in the BaseClass class
  110.  
  111.     MySuperAwesomeClass.set_Value( 7 );
  112.     // Set the Value var in the DerivedClassOne class
  113.  
  114.     MySuperAwesomeClass.set_AnotherValue( 7 );
  115.     // Set the AnotherValue var in the DerivedClassTwo class
  116.  
  117.     // Because I inherited the public methods of DerivedClassTwo which
  118.     // inherited the public methods of DerivedClassOne which inherited
  119.     // the public methods of BaseClass I get access to ALL of their public
  120.     // methods.
  121.     //
  122.     // What causes most people confusion is that in cpp you don't have
  123.     // to implement all methods from each inherited class (and that I
  124.     // can have multiple inherited classes in each class where it can
  125.     // get messy quick).
  126.     //
  127. }
  128.  

This is the basic method to inheritance One->Two->Three->Final. In C++ confusion starts with mutiple inheritance.

Code: [Select]
       +-->Human---+--->Employee--+-->Abused--+--->Intern
       |           |              |           |
       |           |              |           +--->Drafter
       |           |              |           |
       |           |              |           +--->Designer
       |           |              |
       |           |              +--------------->Engineer
       |           |              |
Alive--+           +--->Client    |
       |                          |
       +-->Animal------>Dog-------+--------------->Boss

What I don't like about C# classes, which interfaces will give me [ :) ], is that I cannot have multiple inheritance. This is the reason my intrest was caught when I started on the interfaces chapter. I do not like some aspects of them but I will play around with them more and eventually learn more about them. :)

Kerry, That's almost exactly how I imagined the autodesk API to look like.

Thanks for the tip Locke!

Thank you Mick!
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

JohnK

  • Administrator
  • Seagull
  • Posts: 10625
Re: arrays
« Reply #36 on: July 31, 2014, 06:58:15 PM »
<snip>

A good example of this is something like the ActiveRecords or PDO database api's, they have a simple connection method that is used to connect to any db by using an interface to abstract the actual connection details away. You could do this with inheritance but that would means all the different companies would need to agree on the abstract base class and methods they would all need to use. By using an interface you can change the underlying database connection details without breaking all of the legacy code that uses the connection api. This is a good separation of concerns if you will and TDD pretty much enforces you to code this way.

So now you're thinking "that's more than double the code I really need to write my app" and this may be true at the start but remember some important points:
- you only write code you need, you don't go off writing stuff you think you may need but never use
- you change only the implementation details, not the api
- you have a much better and maintainable architecture, the tests serve as excellent documentation as well
- you run your tests continually throughout your dev process catching bugs as you go
- the tests provide an exact location of a problem when a test fails, setting break points and stepping through code is seldom done.
- all of your testing is automated saving you many more hours debugging than it took to write the tests (this is key!)
- you will have the confidence to change things any time you like as any bugs are quickly found and extra new tests may need to be written and the problem easily fixed.

It's a big topic but well worth the effort I think.
I think I understand but I know I have to get on this topic right away. I like this already.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: arrays
« Reply #37 on: July 31, 2014, 07:19:21 PM »
Quote from: Micky D
This is a good separation of concerns if you will and TDD pretty much enforces you to code this way.

Have you had any joy Testing with AutoCAD Mick ??
If so I'll fly down and talk to you. ( I'll bring some longnecks.)
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: arrays
« Reply #38 on: July 31, 2014, 07:59:05 PM »
Quote from: Micky D
This is a good separation of concerns if you will and TDD pretty much enforces you to code this way.

Have you had any joy Testing with AutoCAD Mick ??
If so I'll fly down and talk to you. ( I'll bring some longnecks.)

Oooh! it's a deal :D

But... I'm in the horrible position at the moment of having written a complete application and now need to write tests for it (....doh!) so I will be doing a great deal of this very soon.

It's quite tempting and natural to use the cad api directly as it saves a lot of extra code but I've separated my code quite a bit, even to the point where I've basically wrapped the Bricscad api (the bits I need) into my own interface. I didn't want cad api code sprinkled all through 'my' application code, any cad 'adapter' code is handled by my interface which I could reuse in any other cad system if required.

I will be extracting this out to its own dll soon so I'll report when I get something set up.
Doing this will enable me to test my main application logic in the normal way in isolation and only leaves a much smaller part that requires the more difficult set up.

I need to revisit some threads here and make a start.
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: arrays
« Reply #39 on: August 01, 2014, 06:23:02 AM »
After revisiting some threads after my other studies I come across a mention to "Automated Testing with the AutoCAD® .NET API" doc by Scott McFarlane from the AU class of 2012/13, this is exactly what I'm trying to describe, a great read.
The big point to take away here is abstracting the 'boiler plate' code away from your app code and why.
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien