473,386 Members | 1,810 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

static creator or new with exception in constructor call

2
I have defined a class A. This class can only be instantiated if certain business rules are met.

The following two options come to mind for implementing the business rules check:

1. Place the business rules checks in the constructor of this class and throw an exception if the business rules aren't met.

Expand|Select|Wrap|Line Numbers
  1.  
  2. A a = new (A); // can throw an exception
  3.  
  4. class A{
  5.  
  6. public:
  7.  
  8. A::A()
  9. {
  10.    if( business rules aren't met)
  11.       throw;
  12.  
  13.    ...
  14. }
  15. }
  16.  
2. Create a static method in this class that checks the business rules and only then creates a new instance of this class .

Expand|Select|Wrap|Line Numbers
  1. a = A::create(); // can throw an exception
  2.  
  3. class A {
  4.  
  5. private:
  6. A::A()
  7. {
  8.  
  9. }
  10.  
  11. public:
  12. static A::create()
  13. {
  14.    if( business rules pass ) {
  15.       a = new(A)
  16.       return a;
  17.    }
  18.    throw exception
  19. }
  20.  
While option (2) appears more complex, a memory alloc isn't performed until absolutely necessary. On failure of the business rules no memory dealloc is necessary.

However option (1) seems standard fare and has the advantage that anyone looking at the code understands what's happening. When the business rules fail a corresponding dealloc and exception is thrown.

Is there a recommended best practice?

Are there creation patterns that can help answer this question?

Thank you
Dec 8 '07 #1
4 1942
weaknessforcats
9,208 Expert Mod 8TB
The business rules should not be in the constructor for class A.

The Create function should not be a member function of class A.

I say this since it appears the business rules have nothing to do with class A but only with the creation of a class A object.

The Create function should not be a member of class A since there may be other business rules that this Create function can't handle, like what if there are multiple sets of business rules and you don't know which one to apply until run time.

The best practice is to create a factory class and the factory class is where the create method is located. Your code should look like:

Expand|Select|Wrap|Line Numbers
  1. Factory* f = newFactory;
  2. A* obj = 0;
  3. try
  4. {
  5.  obj1 = f->Create(ACCRUAL_BASIS);
  6. }
  7. catch (...)
  8. {
  9.     //etc...
  10. }
  11. delete f;          //remove the factory
  12. //If you get here, no throw and obj is a valid pointer to a class A object.
  13.  
Here the create method has arguments for different sets of business rules: ACCRUAL_BASIS, CASH_BASIS, etc

The factory might look like:
Expand|Select|Wrap|Line Numbers
  1. class Factory
  2. {
  3.     public:
  4.        enum Rules {ACCRUAL_BASIS, CASH_BASIS}
  5.        A*  Create(Rules arg);
  6. };
  7.  
The Factory::Create() method can use the argument to determine which set of rules to test for and can throw if the tests fail.

You might research the Factory design pattern.
Dec 9 '07 #2
hocjr
2
The business rules should not be in the constructor for class A.

The Create function should not be a member function of class A.

I say this since it appears the business rules have nothing to do with class A but only with the creation of a class A object.

The Create function should not be a member of class A since there may be other business rules that this Create function can't handle, like what if there are multiple sets of business rules and you don't know which one to apply until run time.

The best practice is to create a factory class and the factory class is where the create method is located. Your code should look like:

Expand|Select|Wrap|Line Numbers
  1. Factory* f = newFactory;
  2. A* obj = 0;
  3. try
  4. {
  5.  obj1 = f->Create(ACCRUAL_BASIS);
  6. }
  7. catch (...)
  8. {
  9.     //etc...
  10. }
  11. delete f;          //remove the factory
  12. //If you get here, no throw and obj is a valid pointer to a class A object.
  13.  
Here the create method has arguments for different sets of business rules: ACCRUAL_BASIS, CASH_BASIS, etc

The factory might look like:
Expand|Select|Wrap|Line Numbers
  1. class Factory
  2. {
  3.     public:
  4.        enum Rules {ACCRUAL_BASIS, CASH_BASIS}
  5.        A*  Create(Rules arg);
  6. };
  7.  
The Factory::Create() method can use the argument to determine which set of rules to test for and can throw if the tests fail.

You might research the Factory design pattern.

I did not believe the Factory design pattern was a good fit because it was only concerned with creating classes not with "should this class be created". I will reconsider it. Thank you.
Dec 10 '07 #3
RRick
463 Expert 256MB
What W4Cats is suggesting is separating the business rules from the creation of your object. I agree with him that this is a good separation of functionality.

On the other hand I have found the Builder pattern to be helpful in these cases. Factory patterns are usually passed to the object and used throughout the life of the object. In this case, since you are only interested in creating the object with the rules, you can use an intermediate builder object that deals with all the specific details and makes the final decision. For added functionality, you can pass the rules object to the builder.
Dec 11 '07 #4
weaknessforcats
9,208 Expert Mod 8TB
On the other hand I have found the Builder pattern to be helpful in these cases.
Yes, indeed. I neglected to mention that.
Dec 11 '07 #5

Sign in to post your reply or Sign up for a free account.

Similar topics

15
by: Sharon | last post by:
I’m trying to build a generic Publisher-Subscriber that will work over the net, so I’m using the Remoting. I wish that the subscriber user will be notify about the messages sent by the...
6
by: Tamir Khason | last post by:
I have some classes that basicly do the same things but different way. There are no default constructors in those classes each constructor should recieve same value So Fooclass:MyBasicClass...
25
by: Chad Z. Hower aka Kudzu | last post by:
I have defined some implicit convertors so that I can do: MyStruct x = 4; The implicit convert the 4 into MyStruct. But its essentially a copy constructor and thus if I had: MyStruct x;...
6
by: Tony Maresca | last post by:
Given: public class MyClass { private MyClass() {} static MyClass() { //.. }
2
by: superseed | last post by:
Hi, I'm pretty new to C#, and I'm quite stuck on the following problem. I would like to add to my application a Windows.Form (singleton) on which I could display a message of one of the...
7
by: Morgan Cheng | last post by:
In the book *Programming C#* 4th editionby Jesse Liberty, it reads "Actually, the CLR guarantees to start running the static constructor before anything else is done with your class. However, it...
8
by: =?Utf-8?B?cnZtYWNjb3VudA==?= | last post by:
It seems the static constructor is supposed to be called, ONLY once for a particular type. If that's the case, why does the following code throws an exception? using System; using...
2
by: titan.nyquist | last post by:
I need to initialize data to be stored in a static class (for all my code to see), but I'm lost on how to do so. If I use the class constructor, what if it fails? I am reading it information...
5
by: Dave | last post by:
Hello, Suppose you have a class with a static property with only a get (read only). You also have code in a static constructor that sets these properties but takes 1 hour to run. Now suppose...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.