Welcome! Log In Create A New Profile

Advanced

Exam 2009 Q & A

Posted by CountZero 
Announcements Last Post
Announcement SoC Curricula 09/30/2017 01:08PM
Announcement Demarcation or scoping of examinations and assessment 02/13/2017 07:59AM
Announcement School of Computing Short Learning Programmes 11/24/2014 08:37AM
Announcement Unisa contact information 07/28/2011 01:28PM
avatar Re: Exam 2009 Q & A
October 19, 2010 08:34PM
I'll agree with Kyle....
Re: Exam 2009 Q & A
October 19, 2010 10:00PM
Ok, here is my answer set for the past paper. I did not use a reference to the book, so I know some information is off a bit / a lot, and also I have no clue if code samples will work. Criticism welcomed. Anyways, here it is:

Question 1

1.1. I would use the serializer pattern, as it is designed to be able to read in data (in this case XML data) and instantiate the classes necessary by using an Abstract Factory pattern.

1.2. I would motivate the use of the composite design pattern, as XML data (and this example in particular) indicates a parent-child, or otherwise put, hierarchical structure which a composite pattern maps out exactly.



Question 2

2.1 FileVisitor iterates through a file structure (recursively or not, depending on the flag passed as an argument) and for each file matching the filter (again, passed as an argument) it will emit a signal to its observers to be handled accordingly. Code visitor inherits the FileVisitor, but reads each file searching for the text "#include" to identify files containing source code. Once these files are found, the line containing the "#include" statement is added to a QStringList for later use.

2.2. Code as follows:

Language: C++ (QT)
#include <QObject>   // CodeVisitor.h class CodeVisitor : public QObject Q_OBJECT { public: CodeVisitor(); int getNumFiles() const; QString getResultString() const; slots: void processFile(QString filename); private: int m_NumFiles; QStringList m_Result; };   // CodeVisitor.cpp void CodeVisitor::processFile(QString filename) { m_Result << filename; QString line; QFile file(filename); file.open(QIODevice::ReadOnly); QTextStream filestream(&file);   while(!filestream.atEnd()) { line = filestream.readLine();   if(line.startsWith("#include")) { m_Result << QString(" %1").arg(line); } }   file.close(); ++m_NumFiles; }

2.3. FileVisitor would not be affected, as it was simply being inherited by the CodeVisitor class previously. It will now emit a signal instead of having the processFile() method overriden. CodeVisitor on the other hand now has given over inversion of control to the FileVisitor. As it no longer inherits the FileVisitor, it is now dependent on the implementation of the FileVisitor, as it can now only react to a signal, but not change any base functionality of the class.

2.4. Code as follows:

Language: C++ (QT)
int main() { FileVisitor fVis("*", true, false); CodeVisitor cVis();   CONNECT(fVis, SIGNAL(foundFile(QString)), cVis, SLOT(processFile(QString)));   // Process file }

2.5. Code as follows:

Language: C++ (QT)
// CodeVisitor.h #include <QObject> #include <QString>   class CodeVisitor : public QObject Q_OBJECT { public: CodeVisitor(QString searchType); int getNumFiles() const; QString getResultString() const; virtual void processInput(QString filename); slots: void processFile(QString filename); private: CodeVisitor* context; int m_NumFiles; QStringList m_Result; };   // CodeVisitor.cpp void CodeVisitor::CodeVisitor(QString searchType) { switch(searchType) { case "IncludeSearcher": { context = new IncludeSearcher(); break; } case "AntiCodeSearcher": { context = new AntiCodeSearcher(); break; } default: { context = 0; } } }   void CodeVisitor::processFile(QString filename) { if(context == 0) return;   context.processInput(filename); }

2.6. Code as follows:

Language: C++ (QT)
// TxtEnderSearcher.h #include "codevisitor.h"   class TxtEnderSearcher : public CodeVisitor { public: TxtEnderSearcher(); int getNumFiles() const; QString getResultString() const; void processInput(QString filename) private: int m_NumFiles; QStringList m_Result; }   // TxtEnderSearcher.cpp void TxtEnderSearcher::processInput(QString filename) { m_Result << filename; QString line; QFile file(filename); file.open(QIODevice::ReadOnly); QTextStream filestream(&file);   while(!filestream.atEnd()) { line = filestream.readLine();   if(!line.endsWith(".txt")) { m_Result << QString(" %1").arg(line); } }   file.close(); ++m_NumFiles; }

Question 3

3.1. A framework is a set of general purpose classes used to aid in consistent design of software. An API (or Application Programmers Interface) is well-documented public interface describing the public classes, interfaces and components forming part of a framework.

3.2. As per the list below:

1 - Source Code - The actual code containing the functions, interfaces and data members of an application.
2 - Library - A compiled package with no main entry-point granting public interfaces to access the needed functionality.
3 - Devel Package - This is a distributable package containing a library of classes along with their header definition files.

Question 4

4.1. As per the code below

Language: C++ (QT)
// MicroLending.h   // Assumptions below #include "Bank.h" #include "CreditBureau.h" #include "RevenueServices.h" // End assumptions   class MicroLending : QObject { Q_OBJECT public: MicroLending() { } // Inline declaration as nothing happens here. bool isEligible(Customer cust, int amount); }   // MicroLending.cpp bool MicroLending::isEligible(Customer cust, int amount) { // No Constructors shown, so creating these with the assumption of no parameters Bank bank(); CreditBureau creditBureau(); RevenueServices revenueServices();   if (bank.hasSufficientFunds(cust, amount) && creditBureau.hasGoodCredit(cust) && revenueServices.hasRegularIncome(cust)) { return true; } else { return false; } }

4.2. As per the code below

Language: C++ (QT)
int main() { Customer cust("ABC Buyer"); bool eligible; int amount = 125000;   MicroLending* mLending();   qDebug() << customer.getName() << "applies for R" << amount << "loan" << endl;   eligible = mLending.isEligible(cust, amount);   qDebug() << customer.getName() << "has been" << (eligible ? "Approved" : "Rejected") << endl; }


4.3. The Structural Category.

4.4. By having all of the necessary code written once in a specific function, you are less likely to fall prey to some common errors that come with some anti-patterns such as "Copy and Paste" coding. The code in the Facade would generally be well-written and well-tested before any production code was written to use it, or that during the course of the Facade being in use, most bugs would have been located and fixed.

4.5. You could use a facade in unison with an Abstract Factory when creating an interface that will instantiate a necessary class using a simplified interface. The Abstract Factory pattern may also be used as an alternative to the Facade class in certain situations.

4.6. As per the code below

Language: C++ (QT)
class MicroLending { public: bool isEligible(Customer cust, int amount); static MicroLending* getInstance(); protected: MicroLending() { } // Inline declaration as nothing happens here. }   // MicroLending.cpp   MicroLending::getInstance() { static MicroLending* instance = 0;   if(instance == 0) { instance = new MicroLending(); instance->setParent(qApp); }   return instance; }


4.7. As per the code below:

Language: C++ (QT)
MicroLending mLending* = MicroLending::instance();

Question 5

5.1. Qt provides a MetaObject compiler (moc) which with each QObject having a QMetaObject attached to it and qmake, allows for automatic generation of code needed to perform certain reflective programming techniques.

5.2. The programmer should do the following:

- Make sure the class extends QObject
- Make sure the class uses the Q_OBJECT macro immediately after its class declaration
- Make sure to wrap all code in #IFNDEF tags so that multiple inclusion does not cause unexpected behaviour
- Ensure that only one class per file is implemented
- Ensure that classes functionality is separated correctly into header and cpp files

5.3. QMetaProperty's a part (aggregation) of QMetaObject. One QMetaProperty has one QMetaObject parent, and one QMetaObject has multiple QMetaProperty children. QMetaProperty's allow for a class to be described as part of the QMetaObject.

5.4. As per the code below:

Language: C++ (QT)
f->metaObject()->superClass()->className();


5.5. By using MVC you gain the following advantages:

- Code complexity is reduced from both the model and view classes when separated
- Changes to code are driven by different forces when comparing models and views. This keeps changes in one from breaking the other, allowing for higher stability.
- This type of separation allows models to be used for multiple implementations, making them super models. ( winking smiley )
- It promotes better design for reuse.
Re: Exam 2009 Q & A
October 20, 2010 11:15AM
I think 2.2 should be as follows

[codevisitor.h]
Class CodeVisitor: public QObject{
Q_OBJECT
public:
CodeVisitor(QString filter “-h”, bool recursive = true);
void getNumFiles() const;
QString getResultString() const;

public slots:
void processFile(QString filename);
signals:
void processEntry(QString filename);

private:
int m_NumFiles;
QStringList m_Result;
FileVisitor* m_fv;
};

[codevisitor.cpp]

connect (m_fv, SIGNAL(foundFile(QString)), this, SLOT(processFile(QString)));
connect (this, SIGNAL(processEntry(QString)), m_fv, SLOT(processEntry(QString)));


If you don't connect to one of FileVisitors slots - How would you start the whole searching process
Re: Exam 2009 Q & A
October 20, 2010 11:26AM
Kyle Wrote:
-------------------------------------------------------
> @Alu - I went a much more simplified route to you.
> They said "alter the CodeVisitor class to use the
> strategy pattern" and I considered the fact that
> the question is worth 5 marks, the steps I
> followed were:
>
> [*] Add a private pointer to an instance of the
> CodeVisitor class
> [*] Create a new pure virtual function called
> processInput(QString filename)
> [*] Changed the processFile(QString) slot method
> to call the new pointers:
> pointer->processInput(QString) method
>
>
> Now all you need to do, is subclass the
> CodeVisitor class, and simply override the
> processInput() method as the processFile() method
> once was. It's dirtier, but gives the strategy
> pattern as they ask for it. I don't see them
> expecting 5 pages of code for a 5 mark question
> (at least I'd hope so).


I fully agree with you, but my post was more aimed at a decent example (since the text book lacks one) than it was at answering the question.
Re: Exam 2009 Q & A
October 20, 2010 11:34AM
@vdWestd - I disagree, if you place the signal/slot connect within the CodeVisitor code you are in fact just doing exactly what the very original code was doing, and have "coupled" to 2 class back together again. You CodeVisitor code is now totally reliant on the existence of FileVisitor class.
Re: Exam 2009 Q & A
October 20, 2010 11:41AM
@Alu - Fair enough. I gotta say, for a book on design patterns, they really made a mess of examples (I.e.: Not bright to use something as complex as the IDv3 Tag lib to show something as simple as the facade pattern.)
Re: Exam 2009 Q & A
October 20, 2010 11:45AM
vdWestd Wrote:
-------------------------------------------------------
> I think 2.2 should be as follows
>
>
> Class CodeVisitor: public QObject{
> Q_OBJECT
> public:
> CodeVisitor(QString filter “-h”, bool
> recursive = true);
> void getNumFiles() const;
> QString getResultString() const;
>
> public slots:
> void processFile(QString filename);
> signals:
> void processEntry(QString filename);
>
> private:
> int m_NumFiles;
> QStringList m_Result;
> FileVisitor* m_fv;
> };
>
>
>
> connect (m_fv, SIGNAL(foundFile(QString)), this,
> SLOT(processFile(QString)));
> connect (this, SIGNAL(processEntry(QString)),
> m_fv, SLOT(processEntry(QString)));
>
>
> If you don't connect to one of FileVisitors slots
> - How would you start the whole searching process


Once CodeVisitor is decoupled from FileVisitor you only need to redefine processFile() as a slot. Once it is defined as a slot you connect it to FileVisitor's signal. Only one connection. Remember FileVisitor is now initialized in the main function, not in CodeVisitor constructor, hence the empty constructor.
Re: Exam 2009 Q & A
October 20, 2010 11:47AM
@Kyle - You telling me, lol, that book was a joke!
Re: Exam 2009 Q & A
October 20, 2010 12:24PM
I agree more with Alucard. You don't actually have put down all the stuff he did only the Process(Strategy) class, the main function(and only some of it) and the FindExtention class. Which is actaully two questions for 10 marks. Also yours would also need to show where FileVisitor is used in the main function, because they ask you to implement the strategy pattern with CodeVisitor and FileVisitor.
Re: Exam 2009 Q & A
October 20, 2010 10:40PM
Guys - can someone please explain how FileVisitor and CodeVisitor are going to work once they are decoupled.

I get the part of FileVisitor emitting a signal that a certain file has been found that meets the search criteria, and that CodeVisitor now has a signal to process the file.
But how does FileVisitor broadcast the name of the file, and how does CodeVisitor receive it? That is, how does CodeVisitor know which file it has to process?

[Edit - 21/10 - 21:14]

Ok - finally got the damn signal/slot mechanism figured.
In FileVisitor the signal is to be defined as:
Language: C++ (QT)
[..] Signals: void foundFile(QString fileName);

Then in the implementation:
Language: C++ (QT)
void FileVisitor::processFile(QString filename) { emit foundFile(filename); }

CodeVisitor then has the slot processFile(QString filename).

In the client code you need to connect the two with QObject::connect(..);
Now how bloody easy was that.....
Re: Exam 2009 Q & A
October 20, 2010 10:52PM
4.5 - When is it appropriate to make use of an abstract factory design pattern in the Facade design pattern?

When the Facade needs to decide which object to create.
In the example given, the Facade acts as a front for all three classes, and creates an object of each. However, if only a subset of the objects where required, then an Abstract Factory and Factory Method could be used to decide which objects to make.
Re: Exam 2009 Q & A
October 20, 2010 10:58PM
4.6

Language: C++ (QT)
class MicroLending : public QObject { Q_OBJECT public: bool isEligible(Customer cust, int amount); static MicroLending* getInstance(); protected: MicroLending() { } // Inline declaration as nothing happens here. }   // MicroLending.cpp   MicroLending::getInstance() { static MicroLending* instance = 0;   if(instance == 0) { instance = new MicroLending(); instance->setParent(qApp); //Must be a QObject to setParent() }   return instance; }
Re: Exam 2009 Q & A
October 20, 2010 11:05PM
4.7

Option 1 - Complex
Language: C++ (QT)
Customer cust("ABC Buyer"); int amount = 125000; [..] eligible = MicroLending::getInstance()->isEligible(cust, amount);

Option 2 - easier to read

Language: C++ (QT)
Customer cust("ABC Buyer"); int amount = 125000; [..] MicroLending *ml = MicroLending::getInstance(); eligible = ml->isEligible(cust, amount);
avatar Re: Exam 2009 Q & A
October 21, 2010 12:10AM
I've updated the first post....smiling smiley
Re: Exam 2009 Q & A
October 21, 2010 08:35AM
AndreB Wrote:
-------------------------------------------------------
> Guys - can someone please explain how FileVisitor
> and CodeVisitor are going to work once they are
> decoupled.
>
> I get the part of FileVisitor emitting a signal
> that a certain file has been found that meets the
> search criteria, and that CodeVisitor now has a
> signal to process the file.
> But how does FileVisitor broadcast the name of the
> file, and how does CodeVisitor receive it? That
> is, how does CodeVisitor know which file it has to
> process?


FileVisitor emits a signal containing the name of a file it visits (the absolute location).
CodeVisitor has a slot that listens to whatever signal it is connected to, the slot is set to receive the name of a file.
FileVisitor emits a signal every time it visits a file and CodeVisitor's slot is setup to do processing on each file under certain conditions (this is all being done one file at a time).
Re: Exam 2009 Q & A
October 21, 2010 08:49AM
@Alucard - thanks,
Can you show me what the signal in FileVisitor looks like, and how it emits a filename as a string?
Re: Exam 2009 Q & A
October 21, 2010 09:10AM
Language: C++ (QT)
void FileVisitor::processFile(QString filename) { emit foundFile(filename);}

All you need to know is that there is a signal (foundFile()) being emitted and that it is emitting a QString. Now you can connect a slot, that receives a QString, to it...

connect(sender, SIGNAL(signal), receiver, SLOT(slot));

so here is a simple example:

Language: C++ (QT)
FileVisitor *fvis = new FileVisitor; CodeVisitor *cvis = new CodeVisitor(); //codevisitor has a slot processFile(QString fileName) connect(fvis, SIGNAL(foundFile(QString)), this, SLOT(processFile(QString))); //we use "this" because cvis is declared here

Done.
Re: Exam 2009 Q & A
October 21, 2010 09:17AM
5.2

Each class that derives from QObject must:
  • Include the Q_OBJECT macro
  • be defined in a separate .h file
  • have the implementation in a separate .cpp file
  • have the class header wrapped in #ifndef
  • have the .cpp file listed in the .pro file in the "Sources" section
  • include Q_PROPERTY macros in the header file describing the class's properties.
Sorry, only registered users may post in this forum.

Click here to login