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 Exam 2009 Q & A
September 13, 2010 10:33PM
What we what to do with this thread is work through the 2009 Exam. smoking smiley

So I'll keep the thread up to date with everyone's help.
And please don't assume the answers are correct, I'm also a student..

1.1 Identify and motivate a design pattern that can be used to read such an XML
document and to create appropriate reward objects when the player wishes to continue the game. [2]

Serializer pattern (to isolate the code to read from the file) followed by the AbstractFactory pattern (to create the different types of objects) //See the post from rezrovs

1.2 Identify and motivate a design pattern that can be used to structure these three rewards
in a class hierarchy using the information given in the XML document. Draw a UML diagram with appropriate
classes of this design pattern. [8]

Composite, because we're representing classes that are composed of other classes. Both Reward and TreasureChest
look to be composite objects and Lamp, MagicMat and TreasureChest are components
See post from Kyle

2.1 Explain briefly the function of the FileVisitor and CodeVisitor classes which follow the Visitor pattern.[2]
Given a path to a directory, FileVisitor traverses all the files and subdirectories in that path.
CodeVisitor open each file and searches for “#include” lines of text in each file.

2.2 Rewrite CodeVisitor so that the FileVisitor and CodeVisitor classes are completely
decoupled so that CodeVisitor can exist independently of FileVisitor. [5]

Language: C++
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);   private: int m_NumFiles; QStringList m_Result; };

connect the FileVisitor signal to CodeVisitor slot

Language: C++ (QT)
[...] FileVisitor fv(filter, recursive, symlink); CodeVisitor cv(filter, recursive);   connect (fv, SIGNAL(foundFile(QString)), cv, SLOT(processFile(QString)));   [...]


2.3 State how the changes made in Question 2.2 would limit the features of the FileVisitor
and CodeVisitor classes.[2]

CodeVisitor is limited because with the changes the recursive directory visiting structure that was inherited from FileVisitor is lost and therefore a CodeVisitor object can, at best, only visit files in the working directory. Any recursive directory/file visiting will have to be re-implemented in CodeVisitor.

FileVisitor is limited because the client code can only plug a FileVisitor object where it is expected and not a derived subclass object through polymorphism, which would probably do more that emitting a signal to indicate that a file has been found. In this particular case, FileVisitor::processFile() does nothing special except emitting a signal whereas CodeVisitor::processFile does something 'interesting'.

2.4 Once the FileVisitor and CodeVisitor classes are decoupled write the necessary code
to utilise these two classes to achieve a file processing task. [3]

Answer:

2.5 Using the decoupled FileVisitor and CodeVisitor classes implement the Strategy pattern
so that different file processing techniques can be included as different strategies. Rewrite CodeVisitor to implement
the Strategy pattern. Include both header and cpp files.[5]

Answer:

2.6Using the solution given to Question 2.5 implement a concrete strategy to check if the file names
end with a .txt extension. Include both header and cpp files.[5]

Answer:

3.1 Describe the relationship between a framework and an Application Programmers’ Interface (API)
referring to Qt4. [2]

A Framework is a large collection of general-purpose classes and conventions designed to improve the consistency of
design. A Framework has a well-documented public Application Programmers’ Interface(API). An API is a description
of public functions, classes, and interfaces in a library.

3.2 One aspect of C++ that makes it very powerful is its ability to package code in several different ways,
which Ezust refer to as containers of code. One example of such a container of code is a class that is a collection of
functions and data members, and descriptions of its lifecycle management. Identify and describe three other terms that are
used to describe containers of code. [6]

(p.171)
namespace – A collection of declarations and definitions, of classes, functions and static members, perhaps spanning multiple files.
header file(.h) – Class definitions, template definitions, function declaration, inline definitions, static object definitions.
source code module(.cpp) – Function definitions, static object definitions.
library(.lib) – An indexed collection of object file linked together.

4.1 Implement the Façade design pattern using a class MicroLending that does the client credit worthiness check
and returns true if the client is eligible or false otherwise. Implement both header and cpp files. [7]

microlending.h
Language: C++ (QT)
#ifndef MICROLENDING_H #define MICROLENDING_H #include <QObject> #include “bank.h” #include “creditbureau.h” #include “revenueservices.h”   class MicroLending: public QObject{ Q_OBJECT public: MicroLending(); ~MicroLending(){} bool isEligible(QString customer, int amount); protected: Customer *m_customer; int m_amount; Bank *bank; CreditBureau *bureau; RevenueServices *sars; }; #endif


microlening.cpp
Language: C++ (QT)
#include “microlending.h”   bool MicroLending::isEligible(QString cust, int amt){ m_customer = cust; m_amount = amt; Bank *bank = new Bank(); CreditBureau *bureau = new CreditBureau(); RevenueServices *sars = new Sars(); if(bank->hasSufficientFunds(m_customer, amount) && bureau->hasGoodCredit(m_customer) && sars->hasRegularIncome(m_customer)) return true; else return false; }


4.2 Write a main() function to demonstrate how the MicroLending class can be used to perform credit worthiness
check of a client. [3]

Language: C++ (QT)
int main(argc, argv){ Customer customer(“John Smith”); int amount = 12500; MicroLending *micro = new MircoLending(); if(micro->isEligible(customer, amount)) qDebug() << customer->getName() << “ has been approved” << endl; else qdebug()<< customer->getName() << “ has been rejected” << endl; }


4.3 Which category of design patterns does Façade pattern belong to? [1]
Structural pattern. The three categories of patterns are Creational, Structural and Behavioural

4.4 As stated in Ezust, Façade defines a higher-level interface that makes the subsystem easier (and safer) to use.
Explain why Façade makes subsystems safer to use. [2]

A façade is a class with a clear simple interface that encapsulates and hides a complicated set of classes and/or functions

4.5 When would it be appropriate to make use of the Abstract Factory design pattern in the Façade design pattern?[2]
Abstract Factory can be used as an alternative to Facade to hide platform-specific classes.
AND
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.

4.6 Rewrite the MicroLending class to make it a Singleton. Include both header and cpp files. [6]
microlending.h
Language: C++ (QT)
#ifndef MICROLENDING_H #define MICROLENDING_H #include <QObject> #include “Bank.h” #include “CreditBureau.h” #include “RevenueServices.h”   class MicroLending:: public QObject{ Q_OBJECT public: ~MicroLending(){} static MicroLending *instance(); bool isEligible(Customer customer, int amount); protected: MicroLending(); Bank *bank; CreditBureau *bureau; RevenueServices *sars; }; #endif
microlending.cpp
Language: C++ (QT)
#include “MicroLending.h”   MicroLending *MicroLending::instance(){ static Singleton *s_instance = 0; if(s_instance == 0){ s_instance = new MicroLending(); s_instance->setParent(qApp); } return s_instance; }


4.7 Rewrite the relevant lines of code in the main() function in Question 4.2 to make use of the Singleton class
MicroLending to perform credit worthiness check of a client. [1]

//only one line will change
MicroLending *mL = new MicroLending();

//will be replaced with
MicroLending *mL = MicroLending::instance();

5.1What support does Qt provide for reflective programming? Explain briefly.[2]
Qt provides the QMetaObject class to support reflective programming. For each object that meets the conditions in question 5.2,
the Meta-Object compiler in Qt (moc) will automatically generate a corresponding QMetaObject which can be retrieved through
QObject's metaObject() method.

5.2 What should a programmer do to ensure that a class in Qt is reflective? [3]
Each class must be defined in a header file, listed in the projects file’s HEADERS, and must include the Q_OBJECT macro in
its class definition.

5.3 Describe the relationship between QMetaObject and QMetaProperty. [2]
The relationship between QMetaObject and QMetaProperty is that QMetaObject maintains a collection of QMetaProperty objects.
One could say that QMetaObject is a composite and QMetaProperty is a component.

5.4 Given the statement Foo *f = new Foo(), where the class Foo has been programmed to support reflection in Qt,
write the necessary code to display the base class of Foo using its generated meta object. [3]

Language: C++
QMetaObject const *baseClassMetaObject = f->metaObject()->superClass(); QString baseClassName = (baseClassMetaObject != 0) ? baseClassMetaObject->className() : QString();

5.5 Discuss advantages of Qt’s model-view programming architecture. [3]
The Model-View pattern describes techniques of separating the underlying data(the model) from the class that presents the user with
a GUI(the view).
Separating the code from view reduces the complexity of each.
Model code and view code have completely different maintenance imperatives - change are driven by completely different factors -
so it is easier to maintain each of them when they are kept separate.
The separation of model from view makes it possible to maintain several different but consistent, views of the same data model.
Re: Exam 2009 Q & A
September 14, 2010 03:53PM
Thank you! You are God sent!
avatar Re: Exam 2009 Q & A
September 14, 2010 09:20PM
5.4

Language: C++ (QT)
QMetaObject const *baseClassMetaObject = f->metaObject()->superClass(); QString baseClassName = (baseClassMetaObject != 0) ? baseClassMetaObject->className() : QString();
avatar Re: Exam 2009 Q & A
September 14, 2010 10:28PM
Thanks Rob!
Re: Exam 2009 Q & A
September 15, 2010 11:07AM
1.1 - Please can you motivate your answer for this question.

In my mind, the Visitor is applied to items of a collection. While DOM is an implementation of the Visitor pattern and the objects in the XML file are probably read into a collection, I don't really see how applying a Visitor to this collection would be useful.

My answer would have been the Serializer pattern (to isolate the code to read from the file) followed by the AbstractFactory pattern (to create the different types of objects).

Thoughts?

4.3 - It's a structural pattern. Wrapper is not a category, the three categories of patterns are Creational, Structural and Behavioural
Re: Exam 2009 Q & A
September 15, 2010 09:59PM
[edited] 1.2) The question is asking for a design to structure the rewards, so I'd go with Composite because we're representing classes that are composed of other classes. Both Reward and TreasureChest look to be composite objects and Lamp, MagicMat and TreasureChest are components.

5.1) Qt provides the QMetaObject class to support reflective programming. For each object that meets the conditions in question 5.2, the Meta-Object compiler in Qt (moc) will automatically generate a corresponding QMetaObject which can be retrieved through QObject's metaObject() method.

5.3) The relationship between QMetaObject and QMetaProperty is that QMetaObject maintains a collection of QMetaProperty objects. One could say that QMetaObject is a composite and QMetaProperty is a component.
avatar Re: Exam 2009 Q & A
September 16, 2010 12:20AM
Thanks rezrovs, I've updated the first post.

I'm not with you on the Q2.1 part?
Re: Exam 2009 Q & A
September 16, 2010 09:31AM
Sorry, I misnumbered that, it should have been 1.2 - I'll update that post too.
avatar Re: Exam 2009 Q & A
September 17, 2010 12:33AM
Yep, now it makes sense! And I agree with you on the answer.
avatar Re: Exam 2009 Q & A
October 11, 2010 11:31PM
I've updated question 4.

Are there really only a few people willing to help with this?

And I'm pretty sure one of them(robanaurochs) isn't even taking COS311 this year, so a big thanks to Rob!
Re: Exam 2009 Q & A
October 12, 2010 09:15AM
Yeah, the forums do seem quite quiet considering exams start next week. I'll be working on this module on the weekend so no doubt I'll have much more to post then. Good luck for your studies smiling smiley
avatar Re: Exam 2009 Q & A
October 12, 2010 02:44PM
Thanks rezrovs! I'll be doing the same this weekend and we can help each other.spinning smiley sticking its tongue out
Re: Exam 2009 Q & A
October 13, 2010 01:34PM
Hey guys, yeah I'm also going to be working on this the coming weekend and week. Actually just figured out today that we writing next Friday the 22nd. Still had it as 19th of November. Big difference!...But yeah I've done all the work during the year and the question you guys have here don't seems that hectic. Will give my input where I can.
Re: Exam 2009 Q & A
October 14, 2010 01:02AM
Hey,
Been going through Ezust making all my notes, (amazing how things start making sense 3rd time round) should hopefully be done by weekend after which will be going through everything here and hopefully add my 2cents worth.

Thanks all for input, very much appreciated.
J
Re: Exam 2009 Q & A
October 14, 2010 12:05PM
Q2.3 My answer would be as follows: CodeVisitor is limited because with the changes the recursive directory visiting structure that was inherited from FileVisitor is lost and therefore a CodeVisitor object can, at best, only visit files in the working directory. Any recursive directory/file visiting will have to be re-implemented in CodeVisitor.

FileVisitor is limited because the client code can only plug a FileVisitor object where it is expected and not a derived subclass object through polymorphism, which would probably do more that emitting a signal to indicate that a file has been found. In this particular case, FileVisitor::processFile() does nothing special except emitting a signal whereas CodeVisitor::processFile does something 'interesting'.

This is only an attempt people therefore any criticism of it is welcome.
Re: Exam 2009 Q & A
October 15, 2010 12:09PM
hi all, thanks for all the help! Unfortunately, I cannot be of much help, but I would have if I knew the answers! God Bless in the exam!
avatar Re: Exam 2009 Q & A
October 15, 2010 12:22PM
@yesh none of us would be here if we knew all the answers...
Re: Exam 2009 Q & A
October 15, 2010 12:30PM
LOL smiling smiley but good luck anyway and this thread has been most helpful to me! i just hope to pass at least!
Re: Exam 2009 Q & A
October 15, 2010 12:32PM
Qu1.2) can anyone post the required UML diagram if possible please?
Re: Exam 2009 Q & A
October 15, 2010 02:24PM
@yesh - dofactory composite UML Class Diagram

If you look at p197 in your text book, it is there too. Slightly more simplified in that there are fewer methods outlined.

email me (mcdonald_conor@hotmail.com) and I will send you my notes on design patterns, which covers all the ones we have done in the course, includes UML, code snippets and some related notes.

I guess this the wrong forum to post this one but just answering your question.
Re: Exam 2009 Q & A
October 15, 2010 03:12PM
thanks,emailed you conman!
Re: Exam 2009 Q & A
October 16, 2010 08:13PM
2.2 - Review

I dont believe the term "completely decoupled" means seperate totally. I still think you want to allow these 2 classes to work with each other, but not be reliant on each other.
For this reason I would rather have CodeVisitor::processFile(QString filename) as a slot similar to FileVisitor, this allows you to still have the 2 classes connect (work) with each if needed.


Language: C++ (QT)
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);   private: int m_NumFiles; QStringList m_Result; };

2.4 -- connect : If my above thoughts are correct then you could connect the FileVisitor signal to CodeVisitor slot
Language: C++ (QT)
[...] FileVisitor fv(filter, recursive, symlink); CodeVisitor cv(filter, recursive);   connect (fv, SIGNAL(foundFile(QString)), cv, SLOT(processFile(QString)));   [...]



Thoughts??
avatar Re: Exam 2009 Q & A
October 16, 2010 08:25PM
@Darren Your solution will work, I think...

I will update the original post, over the weekend smiling smiley
avatar Re: Exam 2009 Q & A
October 16, 2010 08:26PM
@conman Thanks for the link! thumbs up
avatar Re: Exam 2009 Q & A
October 16, 2010 09:03PM
Updated the first post...
Re: Exam 2009 Q & A
October 16, 2010 09:04PM
@CountZero - No worries

@Darren - your classes are "completely decoupled" since they dont rely on each other at all nor know anything about each other; they can aslo compile independently from each other. You have linked them up to interact using Signals and Slots, which is correct, but doesnt mean they are coupled.... Nice solution btw - very similar to the PrimeCount question in the 2008 exam paper.

I hope we get something like this in the exam!!!
avatar Re: Exam 2009 Q & A
October 17, 2010 11:04AM
Coupling does not refer to interaction between classes. It refers to code maintenance. If the classes are tightly coupled, changes in one class will break the code in the coupled classes. Decoupled classes are immune to changes in their respective coding.

Using the signals/slots mechanism would make them completely decoupled because there's no requirement in their design that they need to work together. You could, for instance, connect FileVistor's signals to any other class and FileVisitor will work exactly the same as it always has. You could also connect some other class' signal to the CodeVisitor slot and it will also do whatever it needs to, provided the QString passed through is a valid filename.

Your versions are not completely decoupled though. You still have legacy code in CodeVisitor that deals with stuff that is the domain of FileVisitor. Go back to the pattern. You have two objects, one is the filter class, one is the handling class. CodeVisitor is only responsible for handling file processing, so remove all references to searching through a file system (ie the parameters in the constructor).
Re: Exam 2009 Q & A
October 17, 2010 05:19PM
@roban That did cross my mind when I wrote the 2.4 answer bit, passing the filter and recursive arguments to both just didn't seem right but was thinking more more along the lines of slots and signals so missed it .

4.5
Abstract Factory can be used as an alternative to Facade to hide platform-specific classes.
Re: Exam 2009 Q & A
October 19, 2010 10:42AM
2.4 - 2.6 - just pasting code, hope it helps explain strategy pattern...

Language: C++ (QT)
//[i]process.h[/i] #ifndef PROCESS_H #define PROCESS_H   #include <QObject>   class Process : public QObject { Q_OBJECT public: virtual ~Process() {} virtual int getNumFiles() const = 0; virtual QString getResultString() const = 0; public slots: virtual void processFile(QString fileName) = 0; };   #endif // PROCESS_H

Language: C++ (QT)
//[i]codevisitor.h[/i] #ifndef _CODE_VISITOR_H_ #define _CODE_VISITOR_H_   #include <QStringList> #include <QObject> #include "process.h"   class CodeVisitor : public Process { Q_OBJECT public: CodeVisitor() {} int getNumFiles() const; QString getResultString() const; public slots: void processFile(QString fileName); private: int m_NumFiles; QStringList m_Result; };   #endif

Constructor can be blank...

Language: C++ (QT)
//[i]codevisitor.cpp[/i] #include <QDebug> #include <QFile> #include <QTextStream>   #include "codevisitor.h"   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++; }   int CodeVisitor::getNumFiles() const { return m_NumFiles; }   QString CodeVisitor::getResultString() const { return m_Result.join("\n"); }

Language: C++ (QT)
//[i]findextension.h[/i] #ifndef FINDEXTENSION_H #define FINDEXTENSION_H   #include <QStringList> #include <QObject> #include "process.h"   class FindExtension : public Process { Q_OBJECT public: FindExtension() {} int getNumFiles() const; QString getResultString() const; public slots: void processFile(QString fileName); private: int m_NumFiles; QStringList m_Result; };   #endif // FINDEXTENSION_H

Note how findextension is identical to codevisitor...

Language: C++ (QT)
//[i]findextension.cpp[/i] #include <QDebug> #include "findextension.h"   void FindExtension::processFile(QString fileName) { if (fileName.contains(".txt")) { m_Result << QString(fileName); m_NumFiles++;} }   int FindExtension::getNumFiles() const { return m_NumFiles; }   QString FindExtension::getResultString() const { return m_Result.join("\n"); }

Only processFile() changes...

Language: C++ (QT)
//[i]type.h[/i] #ifndef TYPE_H #define TYPE_H   #include <QObject> //#include <qstd.h>   #include "process.h" #include "codevisitor.h" #include "findextension.h"   //using namespace qstd;   class Type : public QObject { Q_OBJECT public: Type(); void VisitCode(); void FindExe(); int getNoFiles(); QString getList(); public slots: void process(QString fileName); private: Process *m_Process; };   #endif // TYPE_H

Type is where classes are set up...

Language: C++ (QT)
//[i]type.cpp[/i] #include <qstd.h>   #include "type.h" #include "codevisitor.h" #include "findextension.h"   using namespace qstd;   Type::Type() { m_Process = new FindExtension(); }   void Type::VisitCode() { delete m_Process; m_Process = new CodeVisitor(); }   void Type::FindExe() { delete m_Process; m_Process = new FindExtension(); }   int Type::getNoFiles() { return m_Process->getNumFiles(); }   QString Type::getList() { return m_Process->getResultString(); }   void Type::process(QString fileName) { m_Process->processFile(fileName); }

Language: C++ (QT)
//[i]codevisitor-test.cpp[/i] #include <FileVisitor.h> #include <argumentlist.h> #include "type.h" #include <QApplication> #include <qstd.h> using namespace qstd;   void usage(QString appname) { cout << appname << " Usage: \n" << "codevisitor [-r] [-d startdir] [-f filter] [file-list]\n" << "\t-r \tvisitor will recurse into subdirs\n" << "\t-d startdir\tspecifies starting directory\n" << "\t-f filter\tfilename filter to restrict visits\n" << "\toptional list of files to be visited" << endl; }   int main(int argc, char** argv) { ArgumentList al(argc, argv); QString appname = al.takeFirst(); /* app name is always first in the list. */ if (al.count() == 0) { usage(appname); exit(1); } bool recursive(al.getSwitch("-r")); QString startdir(al.getSwitchArg("-d")); QString filter(al.getSwitchArg("-f")); FileVisitor *fvis = new FileVisitor(filter, recursive); Type *cvis = new Type(); cvis->FindExe(); // VisitCode or FindExe qApp->connect(fvis, SIGNAL(foundFile(QString)), cvis, SLOT(process(QString))); if (startdir != QString()) { fvis->processEntry(startdir); } else if (al.size()) { fvis->processFileList(al); } else return 1; cout << "Files Processed: " << cvis->getNoFiles() << endl; cout << cvis->getList() << endl; return 0; }

Test code...

Easy...
Re: Exam 2009 Q & A
October 19, 2010 08:29PM
@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:
  1. Add a private pointer to an instance of the CodeVisitor class
  2. Create a new pure virtual function called processInput(QString filename)
  3. 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).
Sorry, only registered users may post in this forum.

Click here to login