Please do NOT comment on bad practices used here. I am simply trying to tackle abstraction of this scenario with easy-to-describe examples.
I am trying to model a system that allows a user to enter an entity called TASK with certain configuration parameters and later have the TASK perform actions particular to that task.
Some examples of task definitions could be:
* Create a file {filename} in directory {path}.
* Copy file {filename} from {source directory} to {target directory}.
* Open {notepad application}, enter the text {sample text} and save the file as {filename}.
* Open {sample.docx}, type the text {sample text} at the end of the second paragraph.
Each task has a descriptive name and up to 5 parameters. In the examples above, parameters are enclosed in curly braces {}. Users would be instructed to carry on the above tasks and our application will verify if they have been completed. Each task must have the following function:
In a static world, I would create the following classes:
public abstract class TaskBase
{ public abstract void Perform(param1, ... param5); }
public class TaskFileCopy: TaskBase
{ public override void Perform(param1, ... param5) {} }
The problem is, tasks could be practically anything and after the program is compiled and deployed, more tasks need to be added. The first and worst thing that comes to mind is to keep on deriving from TaskBase, implement Perform, recompile and redeploy while keeping previous task results in tact.
Two problems here: By the time we hit 2,000 tasks, we will have at most 2,000 derived classes and secondly, the underlying OODB will be bogged down.
I was thinking of System.AddIn at one point but am convinced that this scenario has a better solution within OOP design.
I doubt that System.AddIn is suitable for this kind of thing. IMHO System.AddIn is for more static APIs and not for something that is going to be extended rapidly. Maybe you could have a look at MEF instead which is simpler and is based on extensibility and composition.
As you say, inheritance is also not the way to go because having 2000 derived classes will be a nightmare.
I think you should look for design patterns that are based on composition instead of inheritance. There are a few of them. One of them is the Composite pattern. With this pattern, you could have some very simple reusable tasks which you can combine into more complicated tasks. You can have tasks that include subtasks, that include subtasks and on and on.
Also you could look at the dynamic languages that can be hosted on the DLR. Like IronPython. You could create a script repository. Each script a task.
Also for inspiration you could have a look at Windows Workflow Foundation and specifically the Activities.
What is kind of obvious is that you need to maximize reuse. Of course this is easier said than done.
Best regards and good luck.
Related
I would like to know what is the difference between the Visitor pattern and using a static method to execute code in separation.
Let's take a look at an example where I might call the Visitor pattern:
new AnalyticsVisitor.accept(myClass);
and this when called in from myClass for example, would move the work into a visitor to execute. It would even garbage collect faster if it's memory intensive.
Now lets take a look at using a simple method to achieve more or less the same thing:
new AnalyticsManager.execute(myClass);
Have I achieved the same thing?
I have code separation.
I can apply this to several data structures
I can add info to legacy code without changing it.
So why use the Visitor pattern instead of just a class (unless for double dispatch)?
This question is still a little confused. I suspect you haven't understood the goal of the Visitor pattern.
As discussed here the visitor pattern is useful when you have complex data structure (such as a parse tree) that is relatively stable (in terms of development), but you want to be able to keep adding new operations on all of its elements. This is clumsy with standard OO techniques.
The technology the visitor pattern is based on is double-dispatch, so when you say "Why use the Visitor pattern unless for double-dispatch?" you are effectively saying "Why use the visitor pattern?"
Your example code only includes the client, so it isn't clear what your new technique actually offers.
The supplied code appears to be backwards for a real visitor pattern. It should be:
my_datastructure.accept(analytics_visitor);
where analytics_visitor inherits from MyDataStructureVisitor, and supplies individual methods for each of the element types that the data structure can hold.
As for the achievements:
"Code separation" is a vague term. The visitor pattern allows the data structure to be defined without all the the operations (putative methods) to be defined. Instead, they can be defined separately - with a cost of poorer encapsulation.)
It isn't clear what it means to apply a visitor pattern to several data structures. Each visitor class is associated with one data structure.
The goal isn't to add 'info' to legacy code. It is to add operations to legacy code.
I'm new to Silverlight, but being dumped right into the fray - good way to learn I suppose :o)
Anyway, the webapp I'm working on has a relatively complex database structure that represents various object types that are linked to each other, and I was wondering 2 things:
1- What is the recommended approach when it comes to dataclasses? Have just one big dataclass, or try and separate it into several smaller dataclasses, keeping in mind they will need to reference each other?
2- If the recommended approach is to have several dataclasses, how do you define the inter-dataclasses references?
I'm asking because I did a small test. In my DB (simplified here, real model is more complex but that's not important), I have a table "Orders" and a table "Parameters". "Orders" has a foreign key on "Parameters". What I did is create 2 dataclasses.
The first one, ParamClass, were I dropped the "Parameters" table only, so I can have a nice "parameter" class. I then created a simple service to add basic SELECT and INSERT functionality.
The second one, OrdersClass, where I dropped both tables, so that the relation between the tables would automatically create a "EntityRef<parameter>" variable inside the "order" class. I then removed the "parameters" class that was automatically created in the OrdersClass dataclass, since the class has already been declared in the ParamClass dataclass. Again I created a small service to test it.
So far so good, it builds happily. The problem is that when I try to handle things on the application code, I added service references for both dataclasses, but it is not happy doing something like:
OrdersServiceReference.order myOrder = new OrdersServiceReference.order();
myOrder.parameter = new ParamServiceReference.parameter(); //<-PROBLEM IS HERE
It comlpains that it cannot implicitly convert from type 'MytestDC.ParamServiceReference.parameter' to 'MytestDC.OrdersServiceReference.parameter'
Do I somehow need to declare some sort of reference to ParamClass from OrdersClass, or how do I "convert" one to the other?
Is this even a recommended and efficient way of doing this?
Since it's a team-project, I initially wanted to separate the dataclasses so that they (and their services) can be easily checked out by one member without checking out the whole entire dataclass.
Any help appreciated!
PS: using Silverlight 4, in case that's important
Based on the widely accepted Single Responsability Principle (SRP), a class should always be responsible for one task, and one task only.
That pretty much invalidates your "one big dataclass" approach.
I would always recommend smaller, more manageable bits that can be combined, instead of one humonguous class that does everything (except brew coffee for you).
Resources for the SRP:
Wikipedia on SRP
OODesign: Single Responsibility Principle
ObjectMentor: list of articles on good app design - which has a few links to PDF documents, like this one on SRP written by Robert C. Martin - the "guru" on proper OO design
OK, some more research let me to this: it is not simple to separate classes from a relational model using LINQtoSQL. I ended up switching to an Entity Framework approach, which itself doesn't deal with it gracefully (see here and there, for example), but at least it solved another major problem I had with LINQtoSQL.
There are other ORMs out there that are apparently much more capable at this (NHibernate comes up often in recommendations), unfortunately, I don't have time to investigate them now, being under such a tight deadline.
As for the referencing, it was quite simple, change the line to:
myOrder.parameter = new OrderServiceReference.parameter();
even though I removed the declaration from that dataclass.
Hope this helps someone!
How can I use the RAD way productively (reusing code). Any
samples, existing libraries, basic
crud generators?
How can I design the OOP way? Which
design patterns to use for
connection, abstracting different
engines/db access layers
(bde-dbexpress-ado), basic CRUD
operations.
I have my own Delphi/MySQL framework that lets me add 'new screens' very rapidly. I won't share it, but I can describe the approach I take:
I use a tabbed interface with a TFrame based hierarchy. I create a tab and link a TFrame into it.
I take care of all the crud plumbing, and concurrency controls using a standard mysql stored procedure implementation. CustomerSEL, CustomerGET, CustomerUPD, CustomerDEL, etc...
My main form essentially contains navbar panel and a panel containing TPageControl
An example of the classes in my hierarchy
TFrame
TMFrame - my derivation, with interface implementations capturing OnShow, OnHide, and some other particulars
--TWebBrowserFrame
--TDataAwareFrame
--TObjectEditFrame
--TCustomerEditFrame
--TOrderEditFrame
etc...
--TObjectListFrame
--TCustomerListFrame
etc...
and some dialogs..
TDialog
TMDialog
--TDataAwareDialog
--TObjectEditDialog
-- TContactEditDialog
etc..
--TObjectSelectDialog
--TContactSelectDialog
etc...
When I add a new object to manage, it could be a new attribute of customers, let's say we want to track which vehicles a customer owns.
create table CustomerVehicles
I run my special sproc generator that creates my SEL, GET, UPD, DEL
test those...
Derive from the base classes I mentioned above, drop some controls. Add a tab to the TCustomerEdit.
Delphi has always the Dataset as the abstract layer, expose this to your GUI via DataSources. Add the dataset to the customer data module, and "register it". My own custom function in my derived datamodule class, TMDataModule
Security control is similarly taken care of in the framework.. I 'Register' components that require a security flag to be visible or enabled.
I can usually add a new object, build the sprocs, add the maintenance screens within an hour.
Of course, that is usually just the start, usually when you add something, you use it for more than tracking. If this a garage application, we want to add the vehicle the customer brought into the garage, id it so we can track the history. But even so, it is fast.
I have tried subcontracting to younger guys using 'newer development tools', and they never seem to believe me when I say I can do this all ten times faster with Delphi! I can do in two hours bug-free what it seems to take them two days and they still have bugs...
DO - Be careful planning your VFI! As someone mentioned, if you want to change the name of a component on one of your parent classes, be prepared for trouble. You will need to open and 'edit' each child in the hierarchy, even if you clean DCU you can still have some DFM hell. I can assure you in 2006 this is still a problem.
DON'T create one monster datamodule
DO take your time in the upfront design, refactoring after you have created a ton of dependents can be a fun challenge, but a nightmare when you have to get something new working quickly!
Be very careful if you use the „put every DB objects into one big data module” (or "few big datamodules" in huge applications) approach. This can make your project having data module so big, that you will have to use HD monitor to see all TXDataset on this datamodule
Bottom line: switch to using specialized classes for business logic instead of big global data modules. Use global data modules with logic ONLY in very small projects.
Well, I strongly suggest you to use Actions (TActionList) when designing your user interface. There are many predefined actions including Next/Prev/Insert/Delete/Edit/Update operations that can be performed on datasets, so it is a good practice to use these actions and link them to buttons/menus on your forms. This prevents repeated code for UI logic.
There is no need for a CRUD generator for Delphi!! Add TDataSource, TDBGrid and TActionList to a form, add predefined data source actions to the action list, link those actions to buttons or menus, and you are done!
For large applications, I use the tiopf object persistance framework. That lets me deal with objects rather than datasets and swap databases easily. Most of my business logic moves into the business object model (BOM) and my forms are pretty dumb. tiopf has a few ways to connect the BOM to forms; persistance aware controls, Ttidataset for data-aware controls and Mogel Gui Mediator classes for connecting to normal controls.
For small and quick apps, I just use data modules and database components. The main things to remember are:
Put as much code in the data modules (and as little in the forms) as possible.
Do multiple data modules broken down by functionality eg the email module, the income module, the invoicing module...
Test, test, test
Use VFI (visual form inheritance). Design a standart DB form. For example, empty DataSet, DataSource, a PageControl consisting of 2 sheets. First will be empty, later on you'll add edit controls to manipulate data at child forms. Add DBGrid to the second sheet. Beware, this isn't the OOP way though, but it's easy and fast.
I would take a look at Data Abstract from Remobjects.
What are the pros and cons of having multiple inheritance?
And why don't we have multiple inheritance in C#?
UPDATE
Ok so it is currently avoided because of the issue with clashes resolving which parent method is being called etc. Surely this is a problem for the programmer to resolve. Or maybe this could be resolve simularly as SQL where there is a conflict more information is required i.e. ID might need to become Sales.ID to resolve a conflict in the query.
Here is a good discussion on the pitfalls of multiple inheritance:
Why should I avoid multiple inheritance in C++?
Here is a discussion from the C# team on why they decided not to allow multiple inheritance:
http://blogs.msdn.com/csharpfaq/archive/2004/03/07/85562.aspx
http://dotnetjunkies.com/WebLog/unknownreference/archive/2003/09/04/1401.aspx
It's just another tool in the toolbox. Sometimes, it is exactly the right tool. If it is, having to find a workaround because the language actually prohibits it is a pain and leads to good opportunities to screw it up.
Pros and cons can only be found for a concrete case. I guess that it's quite rare to actually fit a problem, but who are the language designers to decide how I am to tackle a specific problem?
I will give a pro here based on a C++ report-writer I've been converting to REALbasic (which has interfaces but only single-inheritance).
Multiple inheritance makes it easier to compose classes from small mixin base classes that implement functionality and have properties to remember state. When done right, you can get a lot of reuse of small code without having to copy-and-paste similar code to implement interfaces.
Fortunately, REALbasic has extends methods which are like the extension methods recently added to C# in C# 3.0. These help a bit with the problem, especially as they can be applied to arrays. I still ended up with some class hierarchies being deeper as a result of folding in what were previously multiply-inherited classes.
The main con is that if two classes have a method with the same name, the new subclass doesn't know which one to call.
In C# you can do a form of multiple inheritance by including instances of each parent object within the child.
class MyClass
{
private class1 : Class1;
private class2: Class2;
public MyClass
{
class1 = new Class1;
class2 = new Class2;
}
// Then, expose whatever functionality you need to from there.
}
When you inherit from something you are asserting that your class is of that (base) type in every way except that you may implement something slightly differently or add something to it, its actually extremely rare that your class is 2 things at once. Usually it just has behavour common to 2 or more things, and a better way to describe that generally is to have your class implement multiple interfaces. (or possibly encapsulation, depending on your circumstances)
It's one of those help-me-to-not-shoot-myself-in-the-foot quirks, much like in Java.
Although it is nice to extend fields and methods from multiple sources (imagine a Modern Mobile Phone, which inherits from MP3 Players, Cameras, Sat-Navs, and the humble Old School Mobile Phone), clashes cannot be resolved by the compiler alone.
I used to have one class for one file. For example car.cs has the class car. But as I program more classes, I would like to add them to the same file. For example car.cs has the class car and the door class, etc.
My question is good for Java, C#, PHP or any other programming language. Should I try not having multiple classes in the same file or is it ok?
I think you should try to keep your code to 1 class per file.
I suggest this because it will be easier to find your class later. Also, it will work better with your source control system (if a file changes, then you know that a particular class has changed).
The only time I think it's correct to use more than one class per file is when you are using internal classes... but internal classes are inside another class, and thus can be left inside the same file. The inner classes roles are strongly related to the outer classes, so placing them in the same file is fine.
In Java, one public class per file is the way the language works. A group of Java files can be collected into a package.
In Python, however, files are "modules", and typically have a number of closely related classes. A Python package is a directory, just like a Java package.
This gives Python an extra level of grouping between class and package.
There is no one right answer that is language-agnostic. It varies with the language.
One class per file is a good rule, but it's appropriate to make some exceptions. For instance, if I'm working in a project where most classes have associated collection types, often I'll keep the class and its collection in the same file, e.g.:
public class Customer { /* whatever */ }
public class CustomerCollection : List<Customer> { /* whatever */ }
The best rule of thumb is to keep one class per file except when that starts to make things harder rather than easier. Since Visual Studio's Find in Files is so effective, you probably won't have to spend much time looking through the file structure anyway.
No I don't think it's an entirely bad practice. What I mean by that is in general it's best to have a separate file per class, but there are definitely good exception cases where it's better to have a bunch of classes in one file. A good example of this is a group of Exception classes, if you have a few dozen of these for a given group does it really make sense to have separate a separate file for each two liner class? I would argue not. In this case having a group of exceptions in one class is much less cumbersome and simple IMHO.
I've found that whenever I try to combine multiple types into a single file, I always end going back and separating them simply because it makes them easier to find. Whenever I combine, there is always ultimately a moment where I'm trying to figure out wtf I defined type x.
So now, my personal rule is that each individual type (except maybe for child classes, by which a mean a class inside a class, not an inherited class) gets its own file.
Since your IDE Provides you with a "Navigate to" functionality and you have some control over namespacing within your classes then the below benefits of having multiple classes within the same file are quite worth it for me.
Parent - Child Classes
In many cases i find it quite helpful to have Inherited classes within their Base Class file.
It's quite easy then to see which properties and methods your child class inherits and the file provides a faster overview of the overall functionality.
Public: Small - Helper - DTO Classes
When you need several plain and small classes for a specific functionality i find it quite redundant to have a file with all the references and includes for just a 4-8 Liner class.....
Code navigation is also easier just scrolling over one file instead of switching between 10 files...Its also easier to refactor when you have to edit just one reference instead of 10.....
Overall breaking the Iron rule of 1 class per file provides some extra freedom to organize your code.
What happens then, really depends on your IDE, Language,Team Communication and Organizing Skills.
But if you want that freedom why sacrifice it for an iron rule?
The rule I always go by is to have one main class in a file with the same name. I may or may not include helper classes in that file depending on how tightly they're coupled with the file's main class. Are the support classes standalone, or are they useful on their own? For example, if a method in a class needs a special comparison for sorting some objects, it doesn't bother me a bit to bundle the comparison functor class into the same file as the method that uses it. I wouldn't expect to use it elsewhere and it doesn't make sense for it to be on its own.
If you are working on a team, keeping classes in separate files make it easier to control the source and reduces chances of conflicts (multiple developers changing the same file at the same time). I think it makes it easier to find the code you are looking for as well.
It can be bad from the perspective of future development and maintainability. It is much easier to remember where the Car class is if you have a Car.cs class. Where would you look for the Widget class if Widget.cs does not exist? Is it a car widget? Is it an engine widget? Oh maybe it's a bagel widget.
The only time I consider file locations is when I have to create new classes. Otherwise I never navigate by file structure. I Use "go to class" or "go to definition".
I know this is somewhat of a training issue; freeing yourself from the physical file structure of projects requires practice. It's very rewarding though ;)
If it feels good to put them in the same file, be my guest. Cant do that with public classes in java though ;)
You should refrain from doing so, unless you have a good reason.
One file with several small related classes can be more readable than several files.
For example, when using 'case classes', to simulate union types, there is a strong relationship between each class.
Using the same file for multiple classes has the advantage of grouping them together visually for the reader.
In your case, a car and a door do not seem related at all, and finding the door class in the car.cs file would be unexpected, so don't.
As a rule of thumb, one class/one file is the way to go. I often keep several interface definitions in one file, though. Several classes in one file? Only if they are very closely related somehow, and very small (< 5 methods and members)
As is true so much of the time in programming, it depends greatly on the situation.
For instance, what is the cohesiveness of the classes in question? Are they tightly coupled? Are they completely orthogonal? Are they related in functionality?
It would not be out of line for a web framework to supply a general purpose widgets.whatever file containing BaseWidget, TextWidget, CharWidget, etc.
A user of the framework would not be out of line in defining a more_widgets file to contain the additional widgets they derive from the framework widgets for their specific domain space.
When the classes are orthogonal, and have nothing to do with each other, the grouping into a single file would indeed be artificial. Assume an application to manage a robotic factory that builds cars. A file called parts containing CarParts and RobotParts would be senseless... there is not likely to be much of a relation between the ordering of spare parts for maintenance and the parts that the factory manufactures. Such a joining would add no information or knowledge about the system you are designing.
Perhaps the best rule of thumb is don't constrain your choices by a rule of thumb. Rules of thumb are created for a first cut analysis, or to constrain the choices of those who are not capable of making good choices. I think most programmers would like to believe they are capable of making good decisions.
The Smalltalk answer is: you should not have files (for programming). They make versioning and navigation painful.
One class per file is simpler to maintain and much more clear for anyone else looking at your code. It is also mandatory, or very restricted in some languages.
In Java for instance, you cannot create multiple top level classes per file, they have to be in separate files where the classname and filename are the same.
(C#) Another exception (to one file per class) I'm thinking of is having List in the same file as MyClass. Where I envisage using this is in reporting. Having an extra file just for the List seems a bit excessive.