SOLID and the user interface? - oop

I try to follow the SOLID principles. But every time it comes to user interfaces I find that there's an inherent friction between the clunky screenful of hybrid, aggregated data the customer requires and the nice principles of single-responsibility.
Now it is possible to divide and conquer the various bits and pieces of a typical user interface into single-responsibility classes, but then you run into all sorts of interesting constructional issues because the so-called "separate" pieces of gui actually often turn out to be different views of the same shared state, or at least partial views of overlapping state.
I often end up mashing together fairly clunky controller classes for my views that are not very SOLID-like, but it's fairly inconsistent coding practice, and it bothers me a bit. It just seems like the complexity of splitting it up isn't worth it.
So how do you deal with it ?

Have you looked into presentation patterns (uncomplete writings by Martin Fowler)? I tend to use Presentation Model for complex views and Autonomous View for trivial views. Presentation Model gives you a flexible setup and you can easily test these classes.

I think you're pretty much right. The view of the data might need to be a "clunky screenful of hybrid, aggregated data" if that's what good user experience dictates for your application. For UI, the usability of the UI is more important than trying to stick to coding design principles. Design principles for code shouldn't dictate the way a user interface looks or works. Then you just end up with rigid forms and views that make sense for the code. Do what makes sense for the user.
That being said an MVC/MVP pattern like mentioned above could still help. Separate the view from the presenter. That way you can still insulate your view and keep the SRP for the view. Your presenter is the one that would have to violate SRP and would have multiple reasons for change.

Related

Adapting design to be SOLID

I am working on a very large ASP.NET application. The problem is that there is not a lot of logic behind the design. The original developer chose about ten classes and that was it. There is high coupling and low cohesion. For example, clsPerson holds all the functionality for Person and breakes most of the rules of SOLID.
I have started to incorporate design patterns into my toolkit. My question is: what is the best way to incorporate badly designed classes into the better design. For example, if you had a class clsStudent that contained all the Student functionality to date and then created a class called clsUndergraduate then would you simply derive clsStudent? I realise that a lot of this depends on context but I am looking for general guidelines.
There is a lot of information online that talks about SOLID, but not a lot that talks about how to adapt an existing application to be SOLID.
It could be argued that you should only aim to implement SOLID principles as, and when the need arrives. However, I'm an advocate and believe that it's not difficult to add elements of SOLIDity to your design without too much overhead or heartache.
Trying to move an existing model to a more SOLID model can be difficult. I would suggest taking small, manageable parts and gradually refactoring. If you have the safety net of automated tests, this should be achievable with confidence. If not, make sure you fully understand the scope of the changes you are making. It's easy to introduce subtle bugs. Ultimately, serious changes will be likely to introduce new tests anyway.
Complying with the SRP is likely to be the easiest place to start. Try to define the main responsibility of each class. If they currently have more than one responsibility, note them and look at how these responsibilities can be moved out and elsewhere. For example, many 'God' classes will be managing persistence, validation, initialisation, etc. along with business logic. See if you can begin to take the persistence code out and put it into mappers/repositories/etc.
If you do this logically and sequentially, my experience is that, as you go, making lots of mistakes along the way, the relevance and importance of the other principles will emerge and make themselves, sort of, obvious.
I found that as I experimented with SOLID principles, by reading and re-reading (mainly Bob Martin and ObjectMentor) more clarity emerges as you have practical experience of implementation. Don't forget the opening principles defined in the Gang of Four, also. Concepts like 'favour composition over inheritance' go hand-in-hand with SOLID OO principles.
Bear in mind that SOLID code is generally more complex than non-SOLID code and can, therefore, be harder to maintain and debug by those not familiar with it. Skeptics might lay the accusation of 'over-engineering' at your door, which can be difficult to argue against with those who haven't wrestled with enhancing/fixing tightly coupled, incohesive code.
Good luck. Please feel free to ask more as I'd love to hear the input of others on this subject. It's scope is wide and varied.

N-Tiered application design tool

I'm beginning the design of a medium-sized web application. I usually like to design from the top down, i.e., start at the highest level and design my way down.
I am planning to have the following layers:
Presentation (PHP/Ajax)
Business Logic
Data Access
Database
Now I'd like to start sketching out the major objects in each layer and the interaction between layers. Is there a tool more specific to this purpose than just using a graphics/diagramming tool like Visio?
This is the sort of thing for which UML is intended. There are lots of UML diagram editors around. I hesitate to recommend one over another though. The degree is (probably) lesser than with source code editors, but users still tend to form strong opinions about which are good, bad, or indifferent, so trying to recommend one seems (to me) pretty useless.
The one bit of advice I'd give is not to get too wrapped up in the UML -- it allows you to specify lots of details, often in relatively subtle ways (e.g. whether an arrow-head is hollow or filled). Diagramming the major classes and how they interact at a high level is extremely useful -- but it's easy to go overboard and start trying to include excessive detail. This can be a huge waste of time. Worse, it can tend to lock your thinking into one specific design way too early in the process, before you've done enough to be sure that design is really right.

Are ORM's counterproductive to OO design?

In OOD, design of an object is said to be characterized by its identity and behavior.
Having used ORM's in the past, the primary purpose, in my opinion, revolves around the ability to store/retrieve data. That is to say, ORM objects are not design by behavior, but rather data (i.e. database tables). Case and point: Many ORM tools come with a point-to-a-database-table-and-click-object-generator.
If objects are no longer characterized by behavior this will, in my opinion, muddy the identity and responsibility of the objects. Subsequently, if objects are not defined by a responsibility this could lend a hand to having tightly coupled classes and overall poor design.
Furthermore, I would think that in an application setting, you would be heading towards scalability issues.
So, my question is, do you think that ORM's are counterproductive to OO design? Perhaps the underlying question would be whether or not they are counterproductive to application development.
There's a well-known and oft-ignored impedance mismatch between the requirements of good database design and the requirements of good OO design. Most developers (in my experience) either do not understand this impedance mismatch or do not care. Since it's more common to start with the database and generate the objects from it (rather than the reverse), then yes, you'll end up with objects that are great as a persistence layer but sub-optimal from an OO perspective. (The reverse, generating the database from the object model, makes me want to stab my eyes out.)
Why are they sub-optimal from an OO perspective? Because the objects produced by an ORM are not business objects, even with partial classes and the like. Business objects model behavior. ORM objects model persistence. I'm not going to spend ten paragraphs arguing this distinction. It's something Rocky Lhotka has covered quite well in his books on Business Objects and his CSLA framework. Whether or not you like or use CSLA, I think his arguments are solid ones.
If objects are no longer characterized by behavior this will, in my opinion, muddy the
identity and responsibility of the objects.
The objects in question do have database reading and writing as defined behavior. They just don't have much other than that.
The reality of the situation is pretty simple: object orientation isn't an end in itself, it's a means to an end -- but in some cases it just doesn't do much to improve the end result. A lot of uses for ORM form a case in point -- they are thousands of variations of CRUD applications that don't need or want to attach any real behavior to most of the data they process.
The application as a whole gains flexibility by not encoding much (if any) of the data's "behavior" into the code of the application itself. Instead, they're often better off with that as "dumb" data, that they simply pass through from UI to database and back out to reports and such. With a bit of care, this can allow a substantial level of user customization that's almost impossible to match when you try to treat the data as real objects with real behavior encoded into the application proper.
Of course, there's another side to that: it can make it substantially more difficult to ensure the integrity of the data or that the data is only used appropriately -- I've seen code that accidentally used the wrong field in a calculation, so they were averaging the office numbers instead of office sizes in square feet. Both were user-defined fields that just said the contents should be numeric. The application had no way to know that one made perfect sense, and the other didn't at all.
Case and point: Many OR/M tools come with a point-to-a-database-table-and-click-object-generator.
Yes but there are equal, if not greater numbers or ORM solutions that base themselves off your objects and generate your database tables.
If you start with data and then tramp down forcing auto-generated objects to have object behaviours, yes, you might get confused... But if you start with the object and generate the database as a secondary layer, you end up with something a lot more usable, even if the database isn't perhaps as optimised as it could be.
If you're looking for an excuse not to use ORM, don't use it. I personally find it saves me thousands of lines of code doing trivial things that the ORM does just great.
I don't believe ORM are counterproductive to OO design, unless you want to insist that persistence is an integral part of behavior.
I'd separate persistence from business behavior. You're certainly free to add busines behavior to any object that an ORM generates for you.
I've also seen ORM systems which tend to go from the OO model and generate the database.
If anything, I would say ORMs are more biased towards producing good OO code than they are to producing good database code.
Ideally, a successful ORM bridges the two worlds and your application code would be great from a business domain problem-solving and implementation perspective and your database code and model would be great from a normalization, performance and ETL/reporting/replication whatever perspective.
On systems where it separates your data from behavior it's absolutely counterproductive.
Orm systems tend to analyze existing database tables to create stupid "Objects" in your language. These things are not true objects because they do not contain business behavior, but since people have these structures, they tend to want to use them.
Ruby on Rails (Active Record) actually binds your data to a "Live" class--this is much better.
I've never seen a system I really liked--ActiveRecord is close but it makes a few rubiesque assumptions that I'm not quite comfortable with--the biggest being supplying public setters & getters by default.
But to sum up--I've seen a lot of good OO programmers write screwed up code because of ORM.
As with most questions of this type, it depends on your usage.
The main ways to use ORM tools are:
Define object by data, use this object throughout application code (BAD BAD BAD)
Use ORM objects only for data access, define your own objects with an interpretive layer between (Much Better)
If starting from scratch a 3rd method is to design data from your object model. (Best if possible)
So yes, if you define the object by the data tables and use that throughout your code you will not be using OOD and introducing very poor design and maintenance issues.
But if you only use the ORM objects as a data access tool (replacing ADO) then you are free to use good OOD and ORM together. Sure, more code is required to build the interpretation layer, but enables much better practices, with not much more code required than old ADO code.
I'm answering this from a C# perspective, since that is where I do the majority of my development....
I see your point, but I think with the ability to create partial classes you can still create objects with any behavior you like and still get the power that an OR/M brings to the table for data retrieval.
From what I've seen of ORMs they do not go against OO principles - fairly orthogonal to them in fact. (for info - pretty new to ORM technology, Java perspective)
My reasoning is that ORMs help you store the data members of a class to a persistent store without having to couple to that store and write that code yourself. You still decide on the data members and write the behaviours of a class.
I guess you could abuse ORMs to break OO principles, but then you can do that with anything. You might use tooling to create skeletal data classes from a pre-existing table, but you would still create methods etc.

Where to start when doing a Domain Model?

Let's say I've made a list of concepts I'll use to draw my Domain Model. Furthermore, I have a couple of Use Cases from which I did a couple of System Sequence Diagrams.
When drawing the Domain Model, I never know where to start from:
Designing the model as I believe the system to be. This is, if I am modelling a the human body, I start by adding the class concepts of Heart, Brain, Bowels, Stomach, Eyes, Head, etc.
Start by designing what the Use Cases need to get done. This is, if I have a Use Case which is about making the human body swallow something, I'd first draw the class concepts for Mouth, Throat, Stomatch, Bowels, etc.
The order in which I do things is irrelevant? I'd say probably it'd be best to try to design from the Use Case concepts, as they are generally what you want to work with, not other kind of concepts that although help describe the whole system well, much of the time might not even be needed for the current project. Is there any other approach that I am not taking in consideration here? How do you usually approach this?
Thanks
Whether DDD, or not, I would recommend with determining the ubiquitous language (UL) by interviewing the product owner(s). Establishing communication in a way that will have you and the product owners speaking the same language not only aides in communication, but being able to discuss the project in common terms tends to help the domain model define itself.
So, my answer is basically to discuss, listen, and learn. Software serves a need. Understanding the model from the viewpoint of the experts will lay the solid groundwork for the application.
I'd start by a drawing a class diagram with all the relationships and implement only the classes that are necessary according to the requirements of your application.
You can use an anemic approach (attributes plus getters and setters) to keep things simple and avoid the step of writing business logic in the same step. With an anemic model, the logic would go into a corresponding Service class. That way you can consider Use Cases later on.
I know some people don't appreciate this way of doing things but it does help with maintenance and avoids some dependency issues.
Answer to devoured elysium's question below:
In terms of analysis, starting with Use cases (What) and then proceeding to the class diagram (How) sounds like a good rule of thumb. Personally, I'd do the Sequence diagram (When and Who?) afterwards, as you'd need to know between which processes/objects messages need to be sent.
Beyond that my take on things is that UML is simply a way to model a system/project and not a methodology by itself (unlike Merise, RAD, RUP, Scrum, etc.). There is nothing stopping someone starting off with any diagram as long as they have the sufficient information to complete it. In fact, they should be done simultaneously since each of the diagrams is a different perspective of the same system/project.
So, all in all it depends on how you go about the analysis. During my studies I was taught the rigid waterfall approach, where you do a complete analysis from start to finish before producing some code. However, things can be different in practice, as the imperative might be to produce a working application in the least time possible.
For example, I was introduced to the Scrum methodology recently for an exercise involving the creation of a web site where people can post their fictions. As there was a time constraint and a clear vision of what should be achieved, we started right away with a bare bones class diagram to represent the domain model. The Use cases were then deduced from a series of mock screens we'd produced.
From memory, the classes were Story, Chapter, User and Category. This last class was phased out in favour of a more flexible Tag class. As you'd imagine, the complete class diagram of the existing project would be much more complex due to applying domain driven design and the specificities of the Java programming language.
This approach could be viewed as sloppy. However, a web site like this could easily be made in a couple of weeks using an iterative process and still be well designed. The advantage an iterative process has over the waterfall approach is that you can continually adjust requirements as you go. Frequent requirements changing is a reality, as people will often change their minds and the possibility of producing a working application after each iteration allows one to stay on course so to speak.
Of course, when you're presenting a project to a client, a complete analysis with UML diagrams and some mock screens would be preferable so they have an idea of what you're offering. This is where the UML comes in. Once you've explained some of the visual conventions, an individual should be able to understand the diagrams.
To finish off, if you're in the situation where you're trying to determine what a client wants, it's probably a good idea to gradually build up a questionnaire you can bring with you. Interviewing a person is the only way you can determine what concepts/features are really needed for an application, and you should expect to go back in order to clarify certain aspects. Another tip would be to do some quick research on the web when you're confronted with a subject matter you're unfamiliar with.
In your example, this would be to go through the basics of anatomy. Among other things, this will help you decide what the model should contain and what granularity it should have (What group of organs should be considered? How precise does it need to be? Do only the organs need to modeled or should they be decomposed into their constituents like tissues, cells, chemical composition, etc. ?).
I think the place to start would be whatever feels logical and comfortable. It's probably best to start with the use cases, as they give you clear direction and goals, and help you avoid YAGNI situations. Given that you should be trying to develop a strong domain model, it shouldn't really matter, as the whole picture of the domain is important.
I would like to share my experience for such type of situations. I usually start with writing tests and code. And try to cover one end to end use case. This gives me fair enough idea about problem and at the end I also have something working with me which I can show case to my client. Most of the time subsequent stories build on top of previous one, but it also happens to me that subsequent stories require changes in the previous model I came up with. But this does not impact me as I already have good test coverage. In this way I came up with the model which fits for the current problem, not the model which maps the real world.
You start with Business Requirements which can be formalized or not. If formalized you would use Use Case Diagrams.
For example here are use case diagrams for an e-commerce app:
http://askuml.com/blog/e-commerce/
http://askuml.com/files/2010/07/e-commerce-use-case.jpg
http://askuml.com/files/2010/07/e-commerce-use-case2b.jpg
From these use cases, you can naturally deduce the business entities: product, category of product, shopping cart, ... that is start to prepare class diagrams.
This is best practice in many methodologies but this is also just common sense and natural.
Short answer
Pick a use case, draw some collaboration diagram (and a class diagram) to realize the domain objects involved. Concentrate only on those objects participated in order to accomplish use case goal. Write TDD test case to set the expectation and gradually model your domain classes to meet the expectations. TDD is very helpful to understand the expected behaviors and it helps to get the cleaner domain model. You will see your domain evolve gradually along with the TDD expectations.
Long answer
My personal experience with DDD was not easy. That was because we didn't have necessary foundations in the first place. Our team had many weak points in different areas; requirements were not captured properly and we only had a customer representative who was not really helpful (not involved). We didn't have a proper release plan and developers had a lack of Object Oriented concepts, best principles and so on. The major problem we had was spending so much time on trying to understand the domain logic. We sketched many class diagrams and we never got the domain model right, so we stopped doing that and found out what went wrong. The problem was that we tried too hard to understand the domain logic and instead of communicating we made assumptions on the requirements. We decided to change our approach, we applied TDD, we started writing the expected behavior and coded the domain model to meet the TDD's expectations. Sometimes we got stuck writing TDD test cases because we didn't understand the domain. We straight away talked to the customer representative and tried to get more input. We changed our release strategy; applied agile methodology and release frequently so that we got real feedback from the end user. However, needed to ensure the end user expectation was set at the right level. We refactored based on the feedback, and in that way the domain model evolved gradually. Subsequently, we applied design patterns to improve reusability and maintainability. My point here is that DDD alone cannot survive, we have to build the ecosystem that embraces the domain, developers must have strong OOP concepts and must appreciate TDD and unit test. I would say DDD sits on top of all the OOP techniques and practices.

Practical uses of OOP

I recently had a debate with a colleague who is not a fan of OOP. What took my attention was what he said:
"What's the point of doing my coding in objects? If it's reuse then I can just create a library and call whatever functions I need for whatever task is at hand. Do I need these concepts of polymorphism, inheritance, interfaces, patterns or whatever?"
We are in a small company developing small projects for e-commerce sites and real estate.
How can I take advantage of OOP in an "everyday, real-world" setup? Or was OOP really meant to solve complex problems and not intended for "everyday" development?
My personally view: context
When you program in OOP you have a greater awareness of the context. It helps you to organize the code in such a way that it is easier to understand because the real world is also object oriented.
The good things about OOP come from tying a set of data to a set of behaviors.
So, if you need to do many related operations on a related set of data, you can write many functions that operate on a struct, or you can use an object.
Objects give you some code reuse help in the form of inheritance.
IME, it is easier to work with an object with a known set of attributes and methods that it is to keep a set of complex structs and the functions that operate on them.
Some people will go on about inheritance and polymorphism. These are valuable, but the real value in OOP (in my opinion) comes from the nice way it encapsulates and associates data with behaviors.
Should you use OOP on your projects? That depends on how well your language supports OOP. That depends on the types of problems you need to solve.
But, if you are doing small websites, you are still talking about enough complexity that I would use OOP design given proper support in the development language.
More than getting something to just work - your friend's point, a well designed OO design is easier to understand, to follow, to expand, to extend and to implement. It is so much easier for example to delegate work that categorically are similar or to hold data that should stay together (yes even a C struct is an object).
Well, I'm sure a lot of people will give a lot more academically correctly answers, but here's my take on a few of the most valuable advantages:
OOP allows for better encapsulation
OOP allows the programmer to think in more logical terms, making software projects easier to design and understand (if well designed)
OOP is a time saver. For example, look at the things you can do with a C++ string object, vectors, etc. All that functionality (and much more) comes for "free." Now, those are really features of the class libraries and not OOP itself, but almost all OOP implementations come with nice class libraries. Can you implement all that stuff in C (or most of it)? Sure. But why write it yourself?
Look at the use of Design Patterns and you'll see the utility of OOP. It's not just about encapsulation and reuse, but extensibility and maintainability. It's the interfaces that make things powerful.
A few examples:
Implementing a stream (decorator pattern) without objects is difficult
Adding a new operation to an existing system such as a new encryption type (strategy pattern) can be difficult without objects.
Look at the way PostgresQL is
implemented versus the way your
database book says a database should
be implemented and you'll see a big
difference. The book will suggest
node objects for each operator.
Postgres uses myriad tables and
macros to try to emulate these nodes.
It is much less pretty and much
harder to extend because of that.
The list goes on.
The power of most programming languages is in the abstractions that they make available. Object Oriented programming provides a very powerful system of abstractions in the way it allows you to manage relationships between related ideas or actions.
Consider the task of calculating areas for an arbitrary and expanding collection of shapes. Any programmer can quickly write functions for the area of a circle, square, triangle, ect. and store them in a library. The difficulty comes when trying to write a program that identifies and calculates the area of an arbitrary shape. Each time you add a new kind of shape, say a pentagon, you would need to update and extend something like an IF or CASE structure to allow your program to identify the new shape and call the correct area routine from your "library of functions". After a while, the maintenance costs associated with this approach begin to pile up.
With object-oriented programming, a lot of this comes free-- just define a Shape class that contains an area method. Then it doesn't really matter what specific shape you're dealing with at run time, just make each geometrical figure an object that inherits from Shape and call the area method. The Object Oriented paradigm handles the details of whether at this moment in time, with this user input, do we need to calculate the area of a circle, triangle, square, pentagon or the ellipse option that was just added half a minute ago.
What if you decided to change the interface behind the way the area function was called? With Object Oriented programming you would just update the Shape class and the changes automagically propagate to all entities that inherit from that class. With a non Object Oriented system you would be facing the task of slogging through your "library of functions" and updating each individual interface.
In summary, Object Oriented programming provides a powerful form of abstraction that can save you time and effort by eliminating repetition in your code and streamlining extensions and maintenance.
Around 1994 I was trying to make sense of OOP and C++ at the same time, and found myself frustrated, even though I could understand in principle what the value of OOP was. I was so used to being able to mess with the state of any part of the application from other languages (mostly Basic, Assembly, and Pascal-family languages) that it seemed like I was giving up productivity in favor of some academic abstraction. Unfortunately, my first few encounters with OO frameworks like MFC made it easier to hack, but didn't necessarily provide much in the way of enlightenment.
It was only through a combination of persistence, exposure to alternate (non-C++) ways of dealing with objects, and careful analysis of OO code that both 1) worked and 2) read more coherently and intuitively than the equivalent procedural code that I started to really get it. And 15 years later, I'm regularly surprised at new (to me) discoveries of clever, yet impressively simple OO solutions that I can't imagine doing as neatly in a procedural approach.
I've been going through the same set of struggles trying to make sense of the functional programming paradigm over the last couple of years. To paraphrase Paul Graham, when you're looking down the power continuum, you see everything that's missing. When you're looking up the power continuum, you don't see the power, you just see weirdness.
I think, in order to commit to doing something a different way, you have to 1) see someone obviously being more productive with more powerful constructs and 2) suspend disbelief when you find yourself hitting a wall. It probably helps to have a mentor who is at least a tiny bit further along in their understanding of the new paradigm, too.
Barring the gumption required to suspend disbelief, if you want someone to quickly grok the value of an OO model, I think you could do a lot worse than to ask someone to spend a week with the Pragmatic Programmers book on Rails. It unfortunately does leave out a lot of the details of how the magic works, but it's a pretty good introduction to the power of a system of OO abstractions. If, after working through that book, your colleague still doesn't see the value of OO for some reason, he/she may be a hopeless case. But if they're willing to spend a little time working with an approach that has a strongly opinionated OO design that works, and gets them from 0-60 far faster than doing the same thing in a procedural language, there may just be hope. I think that's true even if your work doesn't involve web development.
I'm not so sure that bringing up the "real world" would be as much a selling point as a working framework for writing good apps, because it turns out that, especially in statically typed languages like C# and Java, modeling the real world often requires tortuous abstractions. You can see a concrete example of the difficulty of modeling the real world by looking at thousands of people struggling to model something as ostensibly simple as the geometric abstraction of "shape" (shape, ellipse, circle).
All programming paradigms have the same goal: hiding unneeded complexity.
Some problems are easily solved with an imperative paradigm, like your friend uses. Other problems are easily solved with an object-oriented paradigm. There are many other paradigms. The main ones (logic programming, functional programming, and imperative programming) are all equivalent to each other; object-oriented programming is usually thought as an extension to imperative programming.
Object-oriented programming is best used when the programmer is modeling items that are similar, but not the same. An imperative paradigm would put the different kinds of models into one function. An object-oriented paradigm separates the different kinds of models into different methods on related objects.
Your colleague seems to be stuck in one paradigm. Good luck.
To me, the power of OOP doesn't show itself until you start talking about inheritance and polymorphism.
If one's argument for OOP rests the concept of encapsulation and abstraction, well that isn't a very convincing argument for me. I can write a huge library and only document the interfaces to it that I want the user to be aware of, or I can rely on language-level constructs like packages in Ada to make fields private and only expose what it is that I want to expose.
However, the real advantage comes when I've written code in a generic hierarchy so that it can be reused later such that the same exact code interfaces are used for different functionality to achieve the same result.
Why is this handy? Because I can stand on the shoulders of giants to accomplish my current task. The idea is that I can boil the parts of a problem down to the most basic parts, the objects that compose the objects that compose... the objects that compose the project. By using a class that defines behavior very well in the general case, I can use that same proven code to build a more specific version of the same thing, and then a more specific version of the same thing, and then yet an even more specific version of the same thing. The key is that each of these entities has commonality that has already been coded and tested, and there is no need to reimpliment it again later. If I don't use inheritance for this, I end up reimplementing the common functionality or explicitly linking my new code against the old code, which provides a scenario for me to introduce control flow bugs.
Polymorphism is very handy in instances where I need to achieve a certain functionality from an object, but the same functionality is also needed from similar, but unique types. For instance, in Qt, there is the idea of inserting items onto a model so that the data can be displayed and you can easily maintain metadata for that object. Without polymorphism, I would need to bother myself with much more detail than I currently do (I.E. i would need to implement the same code interfaces that conduct the same business logic as the item that was originally intended to go on the model). Because the base class of my data-bound object interacts natively with the model, I can instead insert metadata onto this model with no trouble. I get what I need out of the object with no concern over what the model needs, and the model gets what it needs with no concern over what I have added to the class.
Ask your friend to visualize any object in his very Room, House or City... and if he can tell a single such object which a system in itself and is capable of doing some meaningful work. Things like a button isnt doing something alone - it takes lots of objects to make a phone call. Similarly a car engine is made of the crank shaft, pistons, spark plugs. OOPS concepts have evolved from our perception in natural processes or things in our lives. The "Inside COM" book tells the purpose of COM by taking analogy from a childhood game of identifying animals by asking questions.
Design trumps technology and methodology. Good designs tend to incorporate universal principals of complexity management such as law of demeter which is at the heart of what OO language features strive to codify.
Good design is not dependant on use of OO specific language features although it is typically in ones best interests to use them.
Not only does it make
programming easier / more maintainable in the current situation for other people (and yourself)
It is already allowing easier database CRUD (Create, Update, Delete) operations.
You can find more info about it looking up:
- Java : Hibernate
- Dot Net : Entity Framework
See even how LINQ (Visual Studio) can make your programming life MUCH easier.
Also, you can start using design patterns for solving real life problems (design patterns are all about OO)
Perhaps it is even fun to demonstrate with a little demo:
Let's say you need to store employees, accounts, members, books in a text file in a similar way.
.PS. I tried writing it in a PSEUDO way :)
the OO way
Code you call:
io.file.save(objectsCollection.ourFunctionForSaving())
class objectsCollection
function ourFunctionForSaving() As String
String _Objects
for each _Object in objectsCollection
Objects &= _Object & "-"
end for
return _Objects
end method
NON-OO Way
I don't think i'll write down non-oo code. But think of it :)
NOW LET'S SAY
In the OO way. The above class is the parent class of all methods for saving the books, employees, members, accounts, ...
What happens if we want to change the way of saving to a textfile? For example, to make it compactible with a current standard (.CVS).
And let's say we would like to add a load function, how much code do you need to write?
In the OO- way you only need the add a New Sub method which can split all the data into parameters (This happens once).
Let your collegue think about that :)
In domains where state and behavior are poorly aligned, Object-Orientation reduces the overall dependency density (i.e. complexity) within these domains, which makes the resulting systems less brittle.
This is because the essence of Object-Orientation is based on the fact that, organizationally, it doesn't dustinguish between state and behavior at all, treating both uniformly as "features". Objects are just sets of features clumpled to minimize overall dependency.
In other domains, Object-Orientation is not the best approach. There are different language paradigms for different problems. Experienced developers know this, and are willing to use whatever language is closest to the domain.