nestjs mongoose schema model object and an object for service layer in OOP perspective - oop

I am developing a backend with nestjs + mongoose.
As nestjs document suggests, I wrote mongoose schema class following
(this schema has GraphQL decorators , #Prop is mongoose decorator )
#Schema({
timestamps: true,
})
#ObjectType()
#InputType('UserInput')
export class User extends BaseModel {
#Prop()
#Field()
email: string;
#Prop()
#Field({ nullable: true })
username?: string;
...
then in user service layer
async loginUser(loginDto: LoginDto) {
let user: User | undefined = await this.userRepository.findUser(loginDto);
if (!user) {
user = await this.userRepository.createUser(loginDto);
}
I use User object type that user repository returns. this must be same with User Schema that I defined for mongoose with Class.
I think the User Class and user instance ( let user: User | undefined ) returned from userRepositry.findUser violate OOP since the instance can access to all the properties since those properties are public due to use of decorators.
I think I have seen an article that nestjs can't resolve decorators used with private properties inside Class and Nestjs document also doesn't set schema class properties to private . so I didn't set properties in my schema classes to private either
what I doubt about this code is wether I need to create User object which is irrelevant to Schema Class but has same properties in private and instantiate it in service layer for business logic in OOP perspective or not. I think DTO and DAO might be for this use case ? if so , Should I strictly create DTO and DAO in this case ? or ..if there is another way to keep OOP with nestjs and decorators

Related

How to validate email inside entity?

I got this user entity:
class User {
id: string;
name: string;
email: string;
password: string;
....
}
My business rules says that:
One user per Email
What's the purpose of this entity, It cannot have any dependencies. How can i check if email is unique or not?
The thing i don't understand is, who calls entity and pushes data inside it for validation and who can access it?(usecase or repository).
Actually, when you need to satisfy this rule? Only when you are creating a new user. It does not make sense to check it when you've got a user from a database. Or when you are doing something with the user, like changing phonen umber, blocking and so on.
It means this behavior does not belong to User class. I would suggest to create some kind of UserFactory that creates a new user and inject there a policy (or policies).
public UserFactory(EmailCheckingPolicy: emailpolicy, AnotherPolicy: somethingElse);
public User create(UserData: userData) {
if (emailPolicy.isPass(userData.email)) ...
return User(userData.email, userData.name, ...)
}
}
You can inject UserFactory to a UseCase.

How to use singleton with realm object?

I have an User model:
class User: Object, Mappable {
dynamic var account: String?
dynamic var balabala
static var current: User {
return realm.objects(User.self) ?? User()
}
}
But it throws an error: Instance member 'realm' cannot be used on type 'User'
How to use singleton with realm object?
Any help is appreciated
Your User class doesn't define an instance variable called realm, so in your current property the Swift compiler doesn't know what realm refers to.
If you just want to use the default Realm, you need to initialize a new instance of it:
try! Realm().objects(User.self)
Otherwise, as Kam referred to in the comments, set up a separate class for managing your singleton Realm and get the Realm from that class instead.

CWebUser and CUserIdentity

I'm building an authentication module for my application and I don't quite understand the relation between CWebUser and CUserIdentity.
To set the user id to Yii::app()->user->id I have to do that in my UserIdentity class and create a method:
public function getId() {
return $this->_id;
}
But to set isAdmin to Yii::app()->user->isAdmin I have to create a method in my WebUser class:
function getIsAdmin() {
$user = $this->loadUser(Yii::app()->user->id);
return intval($user->user_level_id) == AccountModule::USER_LEVEL_ADMIN;
}
Why can't I just create the methods the UserIdentity class? What is the division of labour here?
The UserIdentity (UI) class is like an ID card, where as the WebUser class is the actual person plus everything you know about them.
The UI class gives you authentication via database, webservices, textfile, whatever. It lets you know what the key attributes are and allows you to manipulate them. The user however can give you more information about what they're allowed to do, there names, granular permissions and such.
OK, end metaphor
The UI class holds the key information, so when asking for the users ID it will refer to the User Identity class to get the Identifier for the user.
Anything that isn't related to identifying or authenticating a user is in the WebUser class
Clear it up at all?
Your example
You gave the getId function as an example, but that can be created on WebUser to override the default, which is to pull from the state.
So not sure what you mean here.
I like how the accepted answer used real life examples to make it easier to understand. However, I also like how Chris explained it here with example.
User information is stored in an instance of the CWebUser class and
this is created on application initialisation (ie: when the User first
connects with the website), irrespective of whether the user is logged
in or not. By default, the user is set to “ Guest”. Authentication is
managed by a class called CUserIdentity and this class checks that the
user is known and a valid user. How this validation occurs will depend
on your application, perhaps against a database, or login with
facebook, or against an ldap server etc...
And what is the benefit of using all those classes? I can do everything just by User model. If I set scenario "login", password will be checked during validation. If validation is OK, I can set to session my own variable like this:
$model = new User("login");
$model->attributes = $_POST["User"];
if ($model->validate())
{
Yii::app()->session["currentUser"] = $model;
}
else
{
// .. show error
unset(Yii::app()->session["currentUser"]);
}
In User model I have then static methods to check this variable
public static function isGuest()
{
return isset(Yii::app()->session["currentUser"]);
}
public static function getCurrent()
{
return Yii::app()->session["currentUser"];
}
And I can call it very shortly:
User::isGuest();
$model = User::getCurrent();
// instead of writing this:
Yii::app()->user->isGuest;
So why should I use so complicated hierarchy of classes that is suggested by Yii? I never understood it.

Model-Service decoupling: what if my model needs a service?

The Service layer is supposed to be on top of the Model layer. As such, models are not supposed to call services.
However, I'm facing a situation where I need to, for example:
interface Component {
getResult();
}
class Number implements Component {
private value;
public getResult() {
return value;
}
}
class Addition implements Component {
private component1;
private component2;
public getResult() {
return component1->getResult() + component2->getResult();
}
}
class ConstantFromExternalSource implements Component {
private identifier;
public getResult() {
// call a service for fetching constant identified by identifier
}
}
(pseudo-code)
Here, my model needs to access an external data source through a Service (webservice or not).
How am I supposed to do in this situation? Is it OK to call a service in the model?
If you suggest to move away the "getResult" method from the model and put it into the "ComponentService", I would disagree because I would then loose all the advantages of OOP (and here my model makes a tree that needs to be recursively resolved, so OOP is the best solution).
You can achieve this in several ways.
First of all you can extract your model's dependency in separate interface like:
interface CustomService {
getResult();
}
class ExternalService implments CustomService
{
getResult() { // access web service }
}
And then inject that dependency into the model:
class ConstantFromExternalSource implements Component {
private identifier;
private CustomService service;
ConstantFromExternalSource(CustomService service)
{
this.service = service;
}
public getResult() {
// call a service for fetching constant identified by identifier
return service.getResult();
}
}
Another way to achieve this is to use Observer Design Pattern and notify higher level abstractions that you need something from them.
In both ways you can decouple you model from concrete implementation of the service layer.
I would have the external source return directly the constant as a Component. I wouldn't couple the ConstantFromExtenralSource class to a service, not even as the interface, because the class (at least in this form) does nothing but call the service.
However if the external source returns some data that needs to be wrapped up in the ConstrantFromExternalSource class, I'd just push the data into the object via the constructor.
In a nutshell, if the model is just an abastraction to get data from an external source, just use a Repository to actulally get the data and to return a model if the external source won't return directly the object you need.
Is it OK to call a service in the model?
Depends on what kind of service. As far as DDD goes,
The domain should definitely not know about the underlying application layer services that consume the domain.
Domain layer services are not much of a problem since they are part of the same layer.
In contrast, Infrastructure layer services have to be injected into your domain objects and their interfaces must be declared in the domain layer if you want loose coupling between domain and infrastructure (same as with repository interfaces/implementations). Sergey has a good implementation of this.

Accessing more than one data provider in a data layer

I'm working on a business application which is being developed using DDD philosophy. Database is accessed through NHibernate and data layer is implemented using DAO pattern.
The UML class diagram is shown below.
UML Class Diagram http://img266.imageshack.us/my.php?image=classdiagramhk0.png
http://img266.imageshack.us/my.php?image=classdiagramhk0.png
I don't know the design is good or not. What do you think?
But the problem is not the design is good or not. The problem is after starting up the application an IDaoFactory is instantiated in presentation layer and send as parameter to presenter classes(which is designed using MVC pattern) as below
...
IDaoFactory daoFactory = new NHibernateDaoFactory(); //instantiation in main class
...
SamplePresenterClass s = new SamplePresenterClass(daoFactory);
...
Using just one data provider (which was just one database) was simple. But now we should get data from XML too. And next phases of the development we should connect to different web services and manipulate incoming and outgoing data.
The data from XML is going to be got using a key which is an enum. We add a class named XMLLoader to the data layer and add an interface ILoader to the domain. XMLLoader has a method whose signature is
List<string> LoadData(LoaderEnum key)
If we instantiate ILoader with XMLLoader in presentation layer as below we have to send it to objects which is going to get some XML data from data layer.
ILoader loader = new XMLLoader();
SamplePresenterClass s = new SamplePresenterClass(daoFactory, xmlLoader);
After implementing web service access classes
SamplePresenterClass s = new SamplePresenterClass(daoFactory, xmlLoader, sampleWebServiceConnector1, sampleWebServiceConnector2, ...);
The parameters is going to be grown in time. I think i can hold all instances of data access objects in a class and pass it to required presenters (maybe singleton pattern can helps too). In domain layer there must be a class like this,
public class DataAccessHolder
{
private IDaoFactory daoFactory;
private ILoader loader;
...
public IDaoFactory DaoFactory
{
get { return daoFactory; }
set { daoFactory = value; }
}
...
}
In main class the instantiation can be made with this design as follows
DataAccessHolder dataAccessHolder = new DataAccessHolder();
dataAccessHolder.DaoFactory = new NHibernateDaoFactory();
dataAccessHolder.Loader = new XMLLoader();
...
SamplePresenterClass s = new SamplePresenterClass(dataAccessHolder);
What do you think about this design or can you suggest me a different one?
Thanks for all repliers...
IMO, it would be cleaner to use a "global" or static daoFactory and make it generic.
DaoFactory<SamplePresenterClass>.Create(); // or
DaoFactory<SamplePresenterClass>.Create(id); // etc
Then, you can define DaoFactory<T> to take only, say, IDao's
interface IDao
{
IDaoProvider GetProvider();
}
interface IDaoProvider
{
IDao Create(IDao instance);
void Update(IDao instance);
void Delete(IDao instance);
}
Basically instead of passing every constructor your DaoFactory, you use a static generic DaoFactory. Its T must inherit from IDao. Then the DaoFactory class can look at the T provider at runtime:
static class DaoFactory<T> where T : IDao, new()
{
static T Create()
{
T instance = new T();
IDaoProvider provider = instance.GetProvider();
return (T)provider.Create(instance);
}
}
Where IDaoProvier is a common interface that you would implement to load things using XML, NHibernate, Web Services, etc. depending on the class. (Each IDao object would know how to connect to its data provider).
Overall, not a bad design though. Add a bit more OO and you will have a pretty slick design. For instance, each file for the XmlEnums could be implemented as IDao's
class Cat : IDao
{
IDaoProvider GetProvider()
{
return new XmlLoader(YourEnum.Cat);
}
// ...
}