const-correctness when passing complex types - c++

So, I have four classes:
App - this represents the entry-point for the application
MainPage - this represents the home screen
Authenticator - this represents a helper/utility class for authentication
LoginPage - this represents a login screen.
App, MainPage, and LoginPage all have pointers to an Authenticator, and it is, in-fact, passed from App, to MainPage, to LoginPage as the user starts the app, reaches the main screen, and is prompted to log in. App creates MainPage, and if MainPage needs to log in, it creates LoginPage. The Authenticator pointer is passed at creation.
Let's say Authenticator looks something like this:
class Authenticator {
public:
std::string GetToken() const;
void Login(std::string username, std::string pass);
}
Now, App will create a normal, non-const pointer to Authenticator but because I don't want MainPage to be able to modify Authenticator, I want it to store a const pointer to it (ie so it can only call const member functions on it). However, I would like LoginPage to be able to call non-const member functions, like Login(), so when I pass my Authenticator from MainPage to LoginPage, I'll need to cast away the const-ness.
My question is: is it bad to do so in this situation? Should a class that is not allowed to modify an object be able to pass it to one that can? Or would it be better to have App create MainPage and LoginPage at the same time, and give them both the same Authenticator to start with? My only problem with that option is that I create a LoginPage actively, rather than lazily, and I'd prefer to do it lazily.
Thanks in advance.

From the Apps point of view, MainPage is modifying the Authenticator. If it's doing so directly or calling another party (LoginPage) to do it on it's behalf doesn't matter. So MainPage should get a non-const pointer and should then pass this to it's sub page for login.
If you want to make sure that your MainPage does not modify the Authenticator, you could implement a base class for it that stores this pointer and has a method to call the login dialog. The Authenticator is private, the method is protected. You can then derive your own MainPageDerived which has no (legal, non-hacky) chance to modify Authenticator but can call LoginPage if needed.
Note that I said could because for 3 classes I would think that's way overengineered. However, if you have more pages in the future, that may be a valid approach.

You're missing an important part of the concept of logical constness. When a class accepts a pointer (or reference) to a const object, it's promising NEVER to use the pointer/reference in a way that could modify the object. This of course means passing along to someone else who could modify it.
In other words, if MainPage is planning to ask someone to modify the Authenticator for it (that is, pass a non-const pointer to it to someone else), it's also responsible for the modifications, and should thus be storing a non-const pointer to it.

From an interface point of view: if you have MainPage(
Authenticator const* ), you are promessing that nothing MainPage
does will modify the observable state of Authenticator.
Directly or indirectly—if MainPage later passes its
pointer to another class which will modify the object, you've
violated the contract. Thus, in your case, it const-correctness
requires MainPage( Authenticator* ): the code constructing
MainPage doesn't care whether the modifications are direct or
indirect; it just wants to know what the contract is, and that
it is upheld.

Give MainPage only what it needs. You can look at this a few ways. It could need:
An AuthenticationTokenSource which provides an up-to-date Token.
An AuthenticatedExectuor which performs Actions which MainPage defines, but AuthenticatedExectuor provides the authentication as it calls the Action
There are probably other ways, but those are the first that spring to mind.

Related

DryIoc registering default primitives

I have a boostrapper for the Caliburn.Micro MVVM framework where I just auto register all ViewModels in the assembly.
Some ViewModels have constructors with parameters, and I usually overwrite these manually (using the Register-parameter ifAlreadyRegistered: IfAlreadyRegistered.Replace) after my auto-registration is complete.
However, when a ViewModel has a primitive type, DryIoc automatically fills the type with a default value.
When I then manually register the ViewModel with the correct parameter, I get two registrations for the same ViewModel, where Caliburn.Micro will chose the default-filled one.
What is the proposed method of dealing with this stuff?
UPDATE:
ctor ViewModel(DependencyA depA, string[] list)
AssemblySource.Instance.SelectMany(Portable.GetAssemblyTypes)
.Where(type => type.Name.EndsWith("ViewModel"))
.ForEach(type => _container.Register(type));
This get registered as ServiceKey=DefaultKey.Of(0) registered as factory
So I now know what list should be (after the auto-registration), and I register ViewModel again, this time with a different service-key which is linked to the actual string[].
Container.Register<ViewModel>(
made: Parameters.Of.Type<IEnumerable<string>>(typeof(string[])),
serviceKey: "list");
This results in another registration with ServiceKey="list" registered as factory. I would like this named registration to replace the default, but I have to keep the name to actually populate the list.
The reason: Caliburn.Micro will attempt to resolve by type, and I would explicitly have to use Caliburns IoC.Get<>() to provide the key which would mean that I could not inject the ViewModel in the constructor.
As the first attempt, you can try to solve the problem head on: via using container-wide factory selector rule SelectKeyedOverDefaultFactory:
var c = new Container(Rules.Default
.WithFactorySelector(SelectKeyedOverDefaultFactory("preferable key")));
c.Register<I, A>();
c.Register<I, B>(serviceKey: "preferable key");
c.Resolve<I>(); // will resolve I of B
c.Register<X>();
c.Resolve<X>(); // will work as before (w/out rule) by falling back to default factory.
But I plan another way of solving such cases in the next version.

Ember Inject Service into Ember Utility

I know Ember has a logger, but I wanted to create my own for learning purposes. I have a service called logger, and I want to be able to use this service everywhere. I have no problem injecting this service into components, controllers, and etc... I cannot figure out how to inject this service into a Utility I created without passing it through the create function. I don't want to have to pass my logger everywhere I create the utility. When I try to inject it into the object it complains about not being in a container. What's the best way to do this?
Okay, its important to understand what Ember.inject.service actually does! Its like a shorter version for this:
myService: Ember.computed({
get() {
return Ember.getOwner(this).lookup('service:myService);
}
}),
So what is this getOwner? It gives you the owner of an Object. Most of your objects like models, controllers, components, views and so on are created by the Dependency Injection (DI) container. For a class to be available on the DI container it needs to be registered.
Your default classes like controllers, routes, views are automatically registered by the Resolver. After registration you can inject them into other classes automatically when they are created by the container. Also into all instances created by the container the owner is injected.
Because the container itself is private, these public APIs are on the Application. getOwner also returns the application.
If you want to manually lookup an instance on the container you can use lookup.
For your utility class you probably use a normal .create() to get the object. This of course will not automatically couple it to your application, so the owner is not available. Also automatic injection will not work.
You can manually inject the owner with the ownerInjection:
myClass.create(Ember.getOwner(this).ownerInjection(), {...});
Then Ember.inject.service will work because getOwner will return the injected owner.
The other thing you could do is to register your utility objects on the container and then look them up. Then the owner is automatically injected.
Not sure which Ember version initiated this pattern but the Ember documentation contains the answer to that question starting from v4.3:
import { inject as service } from '#ember/service';
import { getOwner, setOwner } from '#ember/application';
class Item {
#service('shopping-cart') cart;
constructor(context) {
setOwner(this, getOwner(context));
}
function addToCart() {
this.cart.add(this);
}
}
// On any framework object...
let item = new Item(this);
item.addToCart();
I hit a similar problem a little while back.
The utilities are of type Ember.Object.
So, all you have to do is inject the service into the Ember.Object class as a property.
Like this:
Ember.Object.reopen({
testService:Ember.inject.service('testService')
});
Et Voila!Now you can literally use your service anywhere

Laravel Tests pass to model to View

I'm mocking my repository correctly, but in cases like show() it either returns null so the view ends up crashing the test because of calling property on null object.
I'm guessing I'm supposed to mock the eloquent model returned but I find 2 issues:
What's the point of implementing repository pattern if I'm gonna end up mocking eloquent model anyway
How do you mock them correctly? The code below gives me an error.
$this->mockRepository->shouldReceive('find')
->once()
->with(1)
->andReturn(Mockery::mock('MyNamespace\MyModel)
// The view may call $book->title, so I'm guessing I have to mock
// that call and it's returned value, but this doesn't work as it says
// 'Undefined property: Mockery\CompositeExpectation::$title'
->shouldReceive('getAttribute')
->andReturn('')
);
Edit:
I'm trying to test the controller's actions as in:
$this->call('GET', 'books/1'); // will call Controller#show(1)
The thing is, at the end of the controller, it returns a view:
$book = Repo::find(1);
return view('books.show', compact('book'));
So, the the test case also runs view method and if no $book is mocked, it is null and crashes
So you're trying to unit test your controller to make sure that the right methods are called with the expected arguments. The controller-method fetches a model from the repo and passes it to the view. So we have to make sure that
the find()-method is called on the repo
the repo returns a model
the returned model is passed to the view
But first things first:
What's the point of implementing repository pattern if I'm gonna end up mocking eloquent model anyway?
It has many purposes besides (testable) consisten data access rules through different sources, (testable) centralized cache strategies, etc. In this case, you're not testing the repository and you actually don't even care what's returned, you're just interested that certain methods are called. So in combination with the concept of dependency injection you now have a powerful tool: You can just switch the actual instance of the repo with the mock.
So let's say your controller looks like this:
class BookController extends Controller {
protected $repo;
public function __construct(MyNamespace\BookRepository $repo)
{
$this->repo = $repo;
}
public function show()
{
$book = $this->repo->find(1);
return View::make('books.show', compact('book'));
}
}
So now, within your test you just mock the repo and bind it to the container:
public function testShowBook()
{
// no need to mock this, just make sure you pass something
// to the view that is (or acts like) a book
$book = new MyNamespace\Book;
$bookRepoMock = Mockery::mock('MyNamespace\BookRepository');
// make sure the repo is queried with 1
// and you want it to return the book instanciated above
$bookRepoMock->shouldReceive('find')
->once()
->with(1)
->andReturn($book);
// bind your mock to the container, so whenever an instance of
// MyNamespace\BookRepository is needed (like in your controller),
// the mock will be loaded.
$this->app->instance('MyNamespace\BookRepository', $bookRepoMock);
// now trigger the controller method
$response = $this->call('GET', 'books/1');
$this->assertEquals(200, $response->getStatusCode());
// check if the controller passed what was returned from the repo
// to the view
$this->assertViewHas('book', $book);
}
//EDIT in response to the comment:
Now, in the first line of your testShowBook() you instantiate a new Book, which I am assuming is a subclass of Eloquent\Model. Wouldn't that invalidate the whole deal of inversion of control[...]? since if you change ORM, you'd still have to change Book so that it wouldn't be class of Model
Well... yes and no. Yes, I've instantiated the model-class in the test directly, but model in this context doesn't necessarily mean instance of Eloquent\Model but more like the model in model-view-controller. Eloquent is only the ORM and has a class named Model that you inherit from, but the model-class as itself is just an entity of the business logic. It could extend Eloquent, it could extend Doctrine, or it could extend nothing at all.
In the end it's just a class that holds the data that you pull e.g. from a database, from an architecture point of view it is not aware of any ORM, it just contains data. A Book might have an author attribute, maybe even a getAuthor() method, but it doesn't really make sense for a book to have a save() or find() method. But it does if you're using Eloquent. And it's ok, because it's convenient, and in small project there's nothing wrong with accessing it directly. But it's the repository's (or the controller's) job to deal with a specific ORM, not the model's. The actual model is sort of the outcome of an ORM-interaction.
So yes, it might be a little confusing that the model seems so tightly bound to the ORM in Laravel, but, again, it's very convenient and perfectly fine for most projects. In fact, you won't even notice it unless you're using it directly in your application code (e.g. Book::where(...)->get();) and then decide to switch from Eloquent to something like Doctrine - this would obviously break your application. But if this is all encapsulated behind a repository, the rest of your application won't even notice when you switch between databases or even ORMs.
So, you're working with repositories, so only the eloquent-implementation of the repository should actually be aware that Book also extends Eloquent\Model and that it can call a save() method on it. The point is that it doesn't (=shouldn't) matter if Book extends Model or not, it should still be instantiable anywhere in your application, because within your business logic it's just a Book, i.e. a Plain Old PHP Object with some attributes and methods describing a book and not the strategies how to find or persist the object. That's what repositories are for.
But yes, the absolute clean way is to have a BookInterface and then bind it to a specific implementation. So it could all look like this:
Interfaces:
interface BookInterface
{
/**
* Get the ISBN.
*
* #return string
*/
public function getISBN();
}
interface BookRepositoryInterface()
{
/**
* Find a book by the given Id.
*
* #return null|BookInterface
*/
public function find($id);
}
Concrete implementations:
class Book extends Model implements BookInterface
{
public function getISBN()
{
return $this->isbn;
}
}
class EloquentBookRepository implements BookRepositoryInterface
{
protected $book;
public function __construct(Model $book)
{
$this->book = $book;
}
public function find($id)
{
return $this->book->find($id);
}
}
And then bind the interfaces to the desired implementations:
App::bind('BookInterface', function()
{
return new Book;
});
App::bind('BookRepositoryInterface', function()
{
return new EloquentBookRepository(new Book);
});
It doesn't matter if Book extends Model or anything else, as long as it implements the BookInterface, it is a Book. That's why I bravely instantiated a new Book in the test. Because it doesn't matter if you change the ORM, it only matters if you have several implementations of the BookInterface, but that's not very likely (sensible?), I guess. But just to play it safe, now that it's bound to the IoC-Container, you can instantiate it like this in the test:
$book = $this->app->make('BookInterface');
which will return an instance of whatever implementation of Book you're currently using.
So, for better testability
Code to interfaces rather than concrete classes
Use Laravel's IoC-Container to bind interfaces to concrete implementations (including mocks)
Use dependency injection
I hope that makes sense.

Ember: adding a mixin to a class after it's been created

I want to add a mixin to an Ember class which has already been created. (The class is defined in a library, actually Ember itself; it's LinkView).
I see that we can do mixin.apply(obj), but this applies the mixin to an instance of the class. I want to add the mixin to the class, so it's automatically mixed-in to all newly created objects.
I attempted to override the init method of the class, using reopenClass, and do mixin.apply(this) there, to apply the mixin to the instance, and then call the original init method, but this does not seem to work because the mixin wiring is set up in the init method and it's already too late by the time I can get to it.
reopenClass does not seem to accept a mixin argument like extend does. Its code seems to suggest that it's doing something with mixins, but whatever it is it doesn't work:
a = Ember.Object.extend().reopenClass(Ember.Mixin.create({mixval: 1});
a.create().get('mixval'); // undefined
I know that I could create my own class with MyLinkView = Ember.LinkView.extend(mixin, ..., but unfortunately the original class name is referenced explicitly within the library, so I really would prefer to figure out how to extend that original class with my mixin.
I experimented with Ember.LinkView = Ember.LinkView.extend(mixin, .... This somehow seems dangerous, although it seems to work. But in this particular case it doesn't help me since the reference within the Ember code (in the definition of the {{link-to}} helper) is to an internal version of the class, not the fully qualified Ember.LinkView.
Any ideas?
The solution is simply
Klass = Parent.extend({init: {...}});
Mixin = Ember.Mixin.create({init: {...}});
Klass.reopen(mixin);
Everything works as expected, including the super chain. In other words, a call to Klass.create().init() will call the mixin's init, and a call to super from there will call the original Klass#init.
In the course of researching this question, I discovered something interesting about reopen. Even if the argument is not a mixin, it is treated as one (internally, it actually creates a temporary one). This means that if you do
Klass.reopen({
init: function() {
this._super.apply(this, arguments);
}
});
The call to super is actually calling the original init, not the init in the parent class. In other words, specifying init in a reopen does not replace the existing init on the class, it more or less layers on top of it. I can't see this behavior documented anywhere in the Ember docs, but it does seem useful in the right situation.

Adding custom functions to Ember.js ArrayControllers

I'm trying to figure out Ember.js and keep hitting what seems like basic problems that are not documented in a way I understand.
I want a object to manage a list of stuff. ArrayController seems to make sense. I assume having that controller load the data from the 3rd party server (youtube) makes the most sense. So My plan is to write some custom functions in the controller to load the data.
App.videoController = Ember.ArrayController.extend({
loadSomeVideos() {
console.log("I have run");
}
});
after I run the above code App.testController.someFunction() does not exist. Why not? I feel like I am missing some basic concept.
When you call Ember.ArrayController.extend, you're actually just extending the class not creating a concrete instance, therefore you can't call loadSomeVideos.
There are a few conventions in Ember that can get you stumped if you're unaware of them. As commented by "Unspecified", you should use the following convention to extend the class.
Please note the upper case VideoController and also the way in which I'm defining the loadSomeVideos method:
App.VideoController = Ember.ArrayController.extend({
loadSomeVideos: function() {
console.log("I have run");
}
});
Now, if you want to run this, you need to create an instance of the App.VideoController class. Once again notice the capitalisation:
App.videoController = App.VideoController.create();
So, I use a lower case v for the instance, and an upper case V for the class. I've just created an instance (App.videoController) of the class (App.VideoController).
To call your method, you need to call it from the instance, like this:
App.videController.loadSomeVideos();
Check out the following two pages in the documentation.
This first page gives you some info about extending classes and then instantiating them so you can call their methods:
http://emberjs.com/guides/object-model/classes-and-instances/
The second page goes into a bit of depth about more advanced methods reopen and reopenClass.
http://emberjs.com/guides/object-model/reopening-classes-and-instances/