#constructor injection with list collection
Explore tagged Tumblr posts
flutteragency · 2 years ago
Text
Utilizing Dependency Injection in Flutter
Tumblr media
Implementing Inversion of Control uses the design pattern known as Dependency Injection (DI). It permits the development of dependent objects outside of a class and provides those objects in various ways to a class. The creation and binding of the dependent things are moved outside the class that depends on them using DI. This results in more flexibility, decoupling, and simpler testing.
In this article, we’ll look at a few simple instances of dependency injection in Flutter.
What would be the purpose of using DI?
I’m not going to get into the logic behind the pattern in detail, but think about the class that follows:
Code:
class CoffeeMachine {
private Grinder grinder = new Grinder();
makeCoffee() {
grinder.grindCoffeeBeans();
// Other steps to make coffee
}
}
The previous class has no fundamental flaws, but it does have two significant issues:
It is impossible to separate and test the CoffeeMachine class using a dummy Grinder. It would not be able to switch between a Manual Grinder and an Electric Grinder without changing the consumer. We can fix these problems easily by creating different instances of CoffeeMachine with different types of grinders, as follows:
class CoffeeMachine {
// Instance of the Grinder class
final Grinder _grinder;
// Constructor for dependency injection
CoffeeMachine(this._grinder);
// Method to make coffee
makeCoffee() {
_grinder.grindCoffeeBeans();
// Other steps to make coffee
}
}
Following the first approach clarifies why a class with many dependents may quickly get out of control.
Flutter’s Dependency Injection
Since Dependency Injection is a simple paradigm, libraries frequently abstract it from developers. These Flutter libraries often use reflection (mirrors in Dart). But there are two problems with Flutter:
For performance-related reasons, mirrors are disabled. It is impractical to send dependencies many layers down the tree due to the nested nature of widgets.
We’ll use the Inject library to solve these problems. Inject uses the following annotations:
@Injector: A builder or collection of modules is used to create an injector, an inversion of a control container. @Module and @Provides: Define classes and methods that provide dependencies to your Flutter app development. @Component: It is used for dependency injection to enable specific modules.
Installation
Since there is no package in the official repository, we must manually install it. As a git package is how I prefer to approach it, I’ll describe its dependencies in the pubspec.yaml file as follows:
Code:
dependencies:
inject:
git:
url: https://github.com/google/inject.dart.git
path: package/inject
dev_dependencies:
build_runner: ^1.3.0
inject_generator:
git:
url: https://github.com/google/inject.dart.git
path: package/inject_generator
Usage
What features do we typically expect from a DI library? Let’s go over a few typical use cases:
Injection of class concrete
It may be as easy as this:
import 'package:inject/inject.dart';
@provide
class TaskService {
// implementation
}
We can use it e.g. with Flutter widgets like this:
@provide
class SomeWidget extends StatelessWidget {
final TaskService _service;
SomeWidget(this._service);
}
Interface Injection
In the beginning, we must define an abstract class with an implementation class, such as:
// Abstract class for CustomerRepository
abstract class CustomerRepository {
Future<list> allUsers();
}
// Implementation of CustomerRepository using Firestore
class FirestoreCustomerRepository implements CustomerRepository {
@override
Future<list> allUsers() {
// Implementation for fetching all users from Firestore
}
}
</list></list>
Now that we have dependencies, we can add them to our module:
import ‘package:inject/inject.dart’;
@module
class UsersServices {
@provide
CustomerRepository customerRepository() => FirestoreCustomerRepository();
}
Tumblr media
Providers
What should we do if we require a provider to continually give us a new class instance rather than an instance of that class to be injected? Or what if having a concrete example in the constructor is preferable to lazily resolving the dependency? The fact that you may request a function returning the required instance, and it will be injected appropriately, is something I didn’t find in the documentation (well, because there isn’t any documentation at all).
Even so, we can define a helper type as follows:
typedef Provider = T Function();
You can also utilize it in classes:
@provide
class SomeWidget extends StatelessWidget {
final Provider _service;
SomeWidget(this._service);
void _someFunction() {
final service = _service();
// use service
}
}
Assisted injection
Since there is no built-in power to inject objects that need only runtime arguments, we can use the typical factory pattern in this situation: create a factory class that takes all the compile-time dependencies and injects them, and then provide a factory method with a runtime argument to make the necessary instance.
Qualifiers, singletons, and asynchronous injection
The library does support all of this. The official example provides a helpful explanation.
Installing it up
The last step is to build an injector (also known as a Dagger component), for example, as follows:
import ‘main.inject.dart’ as g;
@Injector(const [UsersServices, DateResultsServices])
abstract class Main {
@provide
MyApp get app;
static Futurecreate( UsersServices usersModule, DateResultsServices dateResultsModule, ) async { return await g.Main$Injector.create( usersModule, dateResultsModule, ); } }Here, MyApp is the core widget of our application; UserService and DateResultsServices are previously specified modules, and main.inject. Dart is an automatically generated file (more on this later).
We can now describe our primary function as follows:
void main() async {
var container = await Main.create(
UsersServices(),
DateResultsServices(),
);
runApp(container.app);
}
Running
We must utilize build runner to generate the necessary code because inject uses code generation. Use this command to: Code:
flutter packages pub run build_runner build
However, one crucial point is to note: by default, the code is generated into the cache folder, which Flutter does not support (though a solution to this issue is being worked on). Therefore, we must include the file inject_generator.build.yaml with the following information:
builders:
inject_generator:
target: “:inject_generator”
import: “package:inject_generator/inject_generator.dart”
builder_factories:
— “summarizeBuilder”
— “generateBuilder”
build_extensions:
“.dart”:
— “.inject.summary”
— “.inject.dart”
auto_apply: dependents
build_to: source
Wrap up
Dependency injection (DI) is a powerful design pattern that can help you write better Flutter code. It promotes modularity, reusability, testability, and maintainability by decoupling your code from its dependencies.
DI can be complex to implement initially, but many resources are available to help you, including DI libraries such as GetIt and Provider. If you are new to DI or need assistance implementing it in your Flutter project, you may hire flutter expert from a leading Flutter app development company who is always ready to assist you.
Frequently Asked Questions (FAQs)
1. What is dependency injection in Flutter app development?
Dependency injection in Flutter is a design pattern that allows you to decouple your code by injecting dependencies into classes instead of creating them directly.
2. What is dependency injection in use?
Dependency injection is utilized when creating a loosely linked application or making a class independent of its dependencies. The reusability of code can be increased by using dependency injection. If an object’s usage is decoupled, more dependencies can be replaced without altering classes.
3. Why is dependency injection advantageous?
Decreased coupling between classes and their dependencies is a crucial advantage of dependency injection. Programs become more reusable, testable, and manageable by hiding the implementation details from clients.
Content Source: https://flutteragency.com/utilizing-dependency-injection-in-flutter/
0 notes
rapvamshi-blog · 7 years ago
Text
Constructor Injection With Collection
Constructor Injection With Collection
Spring framework provides support of collection framework. The collection in the sense, list, set, map and properties interfaces are included. In this post, we will see how this collection framework will be handled in spring through constructor injection.
Constructor Injection With List Collection:
List allows to add duplicate elements and ‘null’ elements. To set values to list collection then…
View On WordPress
0 notes
suzanneshannon · 5 years ago
Text
Exploring the .NET Core library Coravel for Task Scheduling, Caching, Mailing and more
Coravel claims it is a "Near-zero config .NET Core library that makes Task Scheduling, Caching, Queuing, Mailing, Event Broadcasting (and more) a breeze!" A lovely claim, that is, in fact, true! It's open source and on Github at https://github.com/jamesmh/coravel so give Coravel a star!
Coravel is available on NuGet as a package - as are all things  - or you can also install it's helper CLI with a simple dotnet tool install --global coravel-cli. After this, using coravel easy, early, and often is as simple as:
coravel install
A nice teach that makes it easy, the coravel CLI adds the package reference, restores your project, and reminds you to set it up in ConfigureServices() in Startup.cs. A nice example of a thoughtful library that is trying to make onboarding simpler.
The Coravel CLI is also a nice scaffolder to get you started with item templates:
> coravel Usage: coravel [options] [command] Options: -?|-h|--help Show help information Commands: event install invocable mail
But what is it?
With a somewhat vague name and a list of cool features that may not seem related, you may find yourself wondering WHAT is this and WHY do I need it?
When you start thinking about layering and responsibilities of real production software, you'll note that there are arguably some gaps in the BCL (Base Class Libraries) that .NET makes available, particularly as you move up into the Application Development space.
Scheduled jobs and tasks, simple emailing with Razor Templates, a lightweight event dispatcher, easily queueable background tasks are just some of the higher level primitives you'll find yourself wanting when creating business apps. Coravel collects those buildable elements and allows you to string them together very quickly.
For example, I'll create an "Invocable." Basically just a method that is more 'job-like.' It has business scope and I need to have it invoked later by some schedule or process within my app.
Here I'll register one in my Startup.cs.
services.AddScoped<SendNightlyReportsEmailJob>();
So I need to send a nightly report. That's an invocable thing, and it's also an IMailer because it mails things. Note the injected IMailer in the constructor. All very natural in ASP.NET Core, using Dependency Injection.
public class SendNightlyReportsEmailJob : IInvocable { private IMailer _mailer; public SendNightlyReportsEmailJob(IMailer mailer) { this._mailer = mailer; } public async Task Invoke() { Console.WriteLine("NightlyReportMailable Started...."); await Task.Delay(10000); // You could grab multiple users from a DB query ;) var mailable = new NightlyReportMailable(new UserModel { Name = "Coravel is lovely!", Email = "[email protected]" }); await this._mailer.SendAsync(mailable); Console.WriteLine($"NightlyReportMailable was sent at {DateTime.UtcNow}."); } }
Then I can have this mailed every evening with the Coravel Scheduler:
scheduler.Schedule<SendNightlyReportsEmailJob>().Daily();
But when, right? Easy:
scheduler .Schedule<SendNightlyReportsEmailJob>() .DailyAt(1, 30) .Zoned(TimeZoneInfo.Local);
What if you have a task that needs to happen, but maybe it's either long-running or happening often. You don't want two tasks going at the same time, so PreventOverlapping! Clever.
scheduler .Schedule<DoAThingOften>() .EveryMinute() .PreventOverlapping("DoAThingOften");
And that's just the scheduler. That mail you have to send? You can use Razor Pages to create reach HTML emails! That makes New User Sign Up, or Completed Order very easy to create. All self-contained in your app. I dig it.
Finally note that there's Pro paid version of Coravel that gives you a very professional UI for Jobs and Invocables, and allows you to visually configure your back-end job schedules. A nice way to support open source - especially when you start using it and really depending on it - is to explore very reasonable Pro licenses like those that Pro Coravel has. Impressive stuff, truly.
*I have no relationship with Coravel the project or the Pro licenses, I'm just a fan.
Sponsor: Suffering from a lack of clarity around software bugs? Give your customers the experience they deserve and expect with error monitoring from Raygun.com. Installs in minutes, try it today!
© 2020 Scott Hanselman. All rights reserved.
Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media
      Exploring the .NET Core library Coravel for Task Scheduling, Caching, Mailing and more published first on https://deskbysnafu.tumblr.com/
0 notes
philipholt · 5 years ago
Text
Exploring the .NET Core library Coravel for Task Scheduling, Caching, Mailing and more
Coravel claims it is a "Near-zero config .NET Core library that makes Task Scheduling, Caching, Queuing, Mailing, Event Broadcasting (and more) a breeze!" A lovely claim, that is, in fact, true! It's open source and on Github at https://github.com/jamesmh/coravel so give Coravel a star!
Coravel is available on NuGet as a package - as are all things  - or you can also install it's helper CLI with a simple dotnet tool install --global coravel-cli. After this, using coravel easy, early, and often is as simple as:
coravel install
A nice teach that makes it easy, the coravel CLI adds the package reference, restores your project, and reminds you to set it up in ConfigureServices() in Startup.cs. A nice example of a thoughtful library that is trying to make onboarding simpler.
The Coravel CLI is also a nice scaffolder to get you started with item templates:
> coravel Usage: coravel [options] [command] Options: -?|-h|--help Show help information Commands: event install invocable mail
But what is it?
With a somewhat vague name and a list of cool features that may not seem related, you may find yourself wondering WHAT is this and WHY do I need it?
When you start thinking about layering and responsibilities of real production software, you'll note that there are arguably some gaps in the BCL (Base Class Libraries) that .NET makes available, particularly as you move up into the Application Development space.
Scheduled jobs and tasks, simple emailing with Razor Templates, a lightweight event dispatcher, easily queueable background tasks are just some of the higher level primitives you'll find yourself wanting when creating business apps. Coravel collects those buildable elements and allows you to string them together very quickly.
For example, I'll create an "Invocable." Basically just a method that is more 'job-like.' It has business scope and I need to have it invoked later by some schedule or process within my app.
Here I'll register one in my Startup.cs.
services.AddScoped<SendNightlyReportsEmailJob>();
So I need to send a nightly report. That's an invocable thing, and it's also an IMailer because it mails things. Note the injected IMailer in the constructor. All very natural in ASP.NET Core, using Dependency Injection.
public class SendNightlyReportsEmailJob : IInvocable { private IMailer _mailer; public SendNightlyReportsEmailJob(IMailer mailer) { this._mailer = mailer; } public async Task Invoke() { Console.WriteLine("NightlyReportMailable Started...."); await Task.Delay(10000); // You could grab multiple users from a DB query ;) var mailable = new NightlyReportMailable(new UserModel { Name = "Coravel is lovely!", Email = "[email protected]" }); await this._mailer.SendAsync(mailable); Console.WriteLine($"NightlyReportMailable was sent at {DateTime.UtcNow}."); } }
Then I can have this mailed every evening with the Coravel Scheduler:
scheduler.Schedule<SendNightlyReportsEmailJob>().Daily();
But when, right? Easy:
scheduler .Schedule<SendNightlyReportsEmailJob>() .DailyAt(1, 30) .Zoned(TimeZoneInfo.Local);
What if you have a task that needs to happen, but maybe it's either long-running or happening often. You don't want two tasks going at the same time, so PreventOverlapping! Clever.
scheduler .Schedule<DoAThingOften>() .EveryMinute() .PreventOverlapping("DoAThingOften");
And that's just the scheduler. That mail you have to send? You can use Razor Pages to create reach HTML emails! That makes New User Sign Up, or Completed Order very easy to create. All self-contained in your app. I dig it.
Finally note that there's Pro paid version of Coravel that gives you a very professional UI for Jobs and Invocables, and allows you to visually configure your back-end job schedules. A nice way to support open source - especially when you start using it and really depending on it - is to explore very reasonable Pro licenses like those that Pro Coravel has. Impressive stuff, truly.
*I have no relationship with Coravel the project or the Pro licenses, I'm just a fan.
Sponsor: Suffering from a lack of clarity around software bugs? Give your customers the experience they deserve and expect with error monitoring from Raygun.com. Installs in minutes, try it today!
© 2020 Scott Hanselman. All rights reserved.
Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media
      Exploring the .NET Core library Coravel for Task Scheduling, Caching, Mailing and more published first on http://7elementswd.tumblr.com/
0 notes
t-baba · 5 years ago
Photo
Tumblr media
How to Ensure Flexible, Reusable PHP Code with Insphpect
Insphpect is a tool I wrote as part of my PhD project. It scans code for object-oriented programming techniques that hinder code reusability and flexibility.
Why?
Let me begin with two mundane observations:
Business requirements change over time.
Programmers are not clairvoyant.
New product launches, emergency lockdown regulations, expanding into new markets, economic factors, updated data protection laws: there are lots of potential causes for business software to need updating.
From those two observations we can infer that programmers know that the code they write is going to change, but not what those changes will be or when they will happen.
Writing code in such a way that it can be easily adapted is a skill that takes years to master.
You’re probably already familiar with programming practices that come back and haunt you. Novice programmers quickly realize that global variables are more trouble than they’re worth, and the once incredibly popular Singleton Pattern has been a dirty word for the last decade.
How you code your application has a big impact on how easy it is to adapt to meet new requirements. As you progress through your career, you learn techniques that make adapting code easier. Once you’ve grasped fundamentals of object-oriented programming you wonder how you ever did without it!
If you ask ten developers to produce software, given the same requirements, you’ll get ten different solutions. Some of those solutions will inevitably be better than others.
Consider a ship in a bottle and a model ship made of Lego. Both are model ships, but changing the sails on the ship in a bottle is very difficult, and reusing the parts is near impossible. However, with a Lego ship, you can easily swap out the sails or use the same components to build a model rocket, house or a car.
Certain programming techniques lead to the ship-in-a-bottle approach and make your code difficult to change and adapt.
Insphpect
Insphpect is a tool which scans your code for programming practices that lead to this kind of a ship in a bottle design.
It grades your code based on how flexible it is, and highlights areas where flexibility can be improved.
What does Insphpect look for?
Currently, Insphpect looks for the following:
tight coupling
hardcoded configuration
singletons
setter injection
using the new keyword in a constructor
service locators
inheritance
static methods
global state
files that have more than one role (e.g. defining a class and running some code)
If it detects anything it identifies as inflexible, it highlights the code, explains why it highlighted the issue, then grades your whole project and individual classes on a score of 0-100 (with 100 being no issues detected). As a proof of concept, for some detections it’s able to automatically generate a patch file that re-writes the code to remove the inflexibility entirely.
Take a look a sample report here.
Insphpect is currently in the testing phase, and it would really help my research progress if you can check it out and complete the survey in the “Give your feedback” section of the site.
Background
Are those bad practices really bad, though?
This was one of the more difficult parts of the background research, and you can read about how this was done in detail on the Insphpect website.
However, this can be summarized as:
The opinions of each bad practice were collected from 100 authors per practice.
The author’s opinion on the practice was graded on a scale of 1–5.
The author’s methodological rigor was graded on a scale of 1–7 based on the Jadad score used for clinical trials.
These were then plotted like the graph below:
Each horizontal line represents an article, and the left (orange) bar for each article is the recommendation going from 5 — Avoid this practice at all costs (Far left) — to 1 — Favor this practice over alternatives.
The right (blue) bar for each article is the Jadad style score measuring analytic rigor. A score of seven means the article describes the practice, provides code examples, discusses alternative approaches, provides like-for-like code samples, discusses the pros/cons of each approach and makes a recommendation of which approach should be used.
In the case of the singleton above, authors who compare the singleton to alternative approaches, discuss the pros/cons, etc., are significantly more likely to suggest using alternative approaches.
Walkthrough
Currently, Insphpect allows uploading code via a Git repository URL or a ZIP file.
So not to point out flaws in other people’s work, let’s take a look at one of my own projects to see what it identifies.
We’ll use https://github.com/Level-2/Transphporm as an example project.
This is quite a good example, because it has a very high score on another code-quality tool Scrutinizer.
Firstly, enter the git URL https://github.com/Level-2/Transphporm into the text box at the top of the home page and press “Go”. It will take a few seconds to minutes, depending on the size of the project, and will generate a report that looks something like this:
Once you’re on the report page, you’ll see a summary at the top with an overall grade out of 100, with 100 being very good and 0 being very poor.
Underneath the summary, you’ll see a list of all the classes in the project, each with its own grade.
Don’t worry if your code doesn’t get a perfect score. It’s unlikely that it will. Remember, Insphpect is a tool that identifies flexibility in your code. There are parts of your code (like the entry point) where flexibility isn’t warranted.
For Transphporm, it has highlighted issues in seven classes.
Let’s take a look at some of those. Scroll down to Transphporm\Parser\CssToXpath and click the link. You’ll see a score for that particular class and a list of issues which have been identified.
In this case, it has identified a static variable and a static method. Clicking on one of the red lines will reveal an explanation of why the line was flagged up.
For example, clicking line 12 will give an explanation of why static variables are less flexible than instance variables.
Although there’s a more in-depth explanation of the issues caused by static properties on the report, as a quick refresher, static variables have one value which is shared across all the instances of the class.
This is inherently less flexible than an instance variable, because using an instance variable allows each instance to have a different value.
For example, consider the following:
class User { public static $db; public $id; public $name; public $email; public function save() { $stmt = self::$db->prepare('REPLACE INTO user (id, name, email) VALUES (:id, :name, :email)'); $stmt->execute([ 'id' => $this->id, 'name' => $this->name. 'email' => $this->email ]); } }
Because $db is static, every instance of this class shares the same $db instance and records will always be inserted into the same database.
While this sounds reasonable, let me give you a real-world example.
Continue reading How to Ensure Flexible, Reusable PHP Code with Insphpect on SitePoint.
by Tom Butler via SitePoint https://ift.tt/3gbyg76
0 notes
mbaljeetsingh · 7 years ago
Text
How to Create a Simple Ionic 4 App with Firebase and AngularFire
The Ionic Firebase combination remains one of the most used in terms of a cloud backend, and today we will use the latest version of Ionic with the AngularFire RC11 to build a simple todo application!
Although the todo list example is a bit boring, this guide is especially interesting if you are just starting with Ionic 4 because it also contains some basic routing information but also the usage of the (new) Firestore database of Firebase.
Once you are finished with this tutorial you will have your basic Ionic Firebase app to create, read, update and delete data inside your Firebase database!
Setup the Ionic 4 Firebase App
For now we start with a blank Ionic 4 app and at the time writing this I’m using the beta so we have to append the type of our project to get the version 4 app. Also, we install the needed packages for Firebase and add another page and service, so go ahead and run:
ionic start devdacticFire blank --type=angular
cd devdacticFire
npm install firebase angularfire2
ionic g page pages/todoDetails
ionic g service services/todo
Now you need to make sure you have created a Firebase app so either use an existing project or create a new one inside the console.
To add the connection to your app, go to the dashboard of your Firebase app and hit “Add Firebase to your web app” which will bring up your configuration object. With Ionic 4 we can now simply add this to our app/environments/environment.ts like this:
export const environment = {
  production: false,
  firebase: {
    apiKey: '<your-key>',
    authDomain: '<your-project-authdomain>',
    databaseURL: '<your-database-URL>',
    projectId: '<your-project-id>',
    storageBucket: '<your-storage-bucket>',
    messagingSenderId: '<your-messaging-sender-id>'
  }
};
Finally we need to load the environment configuration and also setup our module to use the AngularFire package, so go ahead and change your app/app.module.ts to:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule, RouteReuseStrategy, Routes } from '@angular/router';
 import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
 import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
 import { AngularFireModule } from 'angularfire2';
import { environment } from '../environments/environment';
import { AngularFirestoreModule } from 'angularfire2/firestore';
 @NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    BrowserModule, IonicModule.forRoot(), AppRoutingModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFirestoreModule,
  ],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}
As we are using the routing system of Angular inside our app now we need to create the routing configuration to navigate around. We will start on the home page and add 2 routes to the same details page, but we can either navigate their without a parameter or with an additional id.
To do so, change your app/app-routing.module.ts to include all the routes:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
 const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'home', loadChildren: './home/home.module#HomePageModule' },
  { path: 'details/:id', loadChildren: './pages/todo-details/todo-details.module#TodoDetailsPageModule' },
  { path: 'details', loadChildren: './pages/todo-details/todo-details.module#TodoDetailsPageModule' },
];
 @NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
To finish the setup head back to your Firebase app and from the menu navigate to Database. In here you can now select the Database you wish to use (if it’s a new project) and we will use the new Firestore database which is basically a NoSQL database.
Also make sure to select the test mode rules for testing so we can easily read and write all objects. Of course you should have reasonable rules in place for a productive app!
Creating the Firebase Service
Now that our app is connected to Firebase we should create a service to interact with our database.
This service will take care of our create, read update and delete functions (CRUD). All of the interaction will happen on our todosCollection which will load the data from the ‘todos’ path inside our database.
But to display the data in realtime and have all the information present when we need it we need to call the snapshotChanges() function. Also, we need to map those elements because normally they wouldn’t contain the ID of the document, and this ID is what you need most of them to update or delete documents.
The other functions are then only calling the operations on our collection or a single doc() inside the database, so nothing spectacular.
Therefore go ahead and change your app/services/todo.service.ts to:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from 'angularfire2/firestore';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
 export interface Todo {
  task: string;
  priority: number;
  createdAt: number;
}
 @Injectable({
  providedIn: 'root'
})
export class TodoService {
  private todosCollection: AngularFirestoreCollection<Todo>;
   private todos: Observable<Todo[]>;
   constructor(db: AngularFirestore) {
    this.todosCollection = db.collection<Todo>('todos');
     this.todos = this.todosCollection.snapshotChanges().pipe(
      map(actions => {
        return actions.map(a => {
          const data = a.payload.doc.data();
          const id = a.payload.doc.id;
          return { id, ...data };
        });
      })
    );
  }
   getTodos() {
    return this.todos;
  }
   getTodo(id) {
    return this.todosCollection.doc<Todo>(id).valueChanges();
  }
   updateTodo(todo: Todo, id: string) {
    return this.todosCollection.doc(id).update(todo);
  }
   addTodo(todo: Todo) {
    return this.todosCollection.add(todo);
  }
   removeTodo(id) {
    return this.todosCollection.doc(id).delete();
  }
}
If you have a service like this in place it’s later really easy to use all the functions while the connection to the database is in one single class!
Loading the Firebase Collection
Now we just need to create our views and classes to use all the great functions of our service. The first is our home page where we display a list of todos.
The class actually only needs to load the data from the service, and initially I used the Observable directly but the result was that data was duplicate or strange loading results happened. Therefore, we can also subscribe to the Observable and update our local todos array which works fine.
For now, change your app/home/home.page.ts to:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { Component, OnInit } from '@angular/core';
import { Todo, TodoService } from '../services/todo.service';
 @Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {
   todos: Todo[];
   constructor(private todoService: TodoService) { }
   ngOnInit() {
    this.todoService.getTodos().subscribe(res => {
      this.todos = res;
    });
  }
   remove(item) {
    this.todoService.removeTodo(item.id);
  }
}
Now we got all the data and just need to iterate the todos inside our view. Therefore we create an ngFor and sliding items so we can both click them to update the details or also mark them as finished.
Here we use the routerLink to construct the URL of the next page, and if you go back to the routing you see that we can open the details with an id parameter, so that route will be called!
I’ve also added the ion-skeleton-text element which is a cool way of indicating that content is loading like you might have seen on Facebook or YouTube!
Finally at the bottom right of the page we add a ion-fab which is floating above the content. Again, this button is not calling a function to push a new page but simply navigates to the details path of our app so we don’t need any additional logic!
Quite nice this routing new, hu?
Now you can go ahead and replace the code inside your app/home/home.page.html with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<ion-header>
  <ion-toolbar color="primary">
    <ion-title>
      Ionic FireTodos
    </ion-title>
  </ion-toolbar>
</ion-header>
 <ion-content>
   <ion-list>
     <ng-container *ngIf="!todos || todos.length == 0">
      <div *ngFor="let n of [0,1,2]" padding>
        <ion-skeleton-text></ion-skeleton-text>
        <p>
          <ion-skeleton-text class="fake-skeleton"></ion-skeleton-text>
        </p>
      </div>
    </ng-container>
     <ion-item-sliding *ngFor="let item of todos">
      <ion-item lines="inset" button [routerLink]="['/details', item.id]">
        <ion-label>
          {{ item.task }}
          <p>{{ item.createdAt | date:'short' }}</p>
        </ion-label>
        <ion-note slot="end" color="primary">{{ item.priority }}</ion-note>
      </ion-item>
       <ion-item-options side="end">
        <ion-item-option (click)="remove(item)" color="secondary">
          Check
          <ion-icon name="checkmark" slot="end"></ion-icon>
        </ion-item-option>
      </ion-item-options>
    </ion-item-sliding>
   </ion-list>
   <ion-fab vertical="bottom" horizontal="end" slot="fixed">
    <ion-fab-button routerLink="/details" routerDirection="forward">
      <ion-icon name="add"></ion-icon>
    </ion-fab-button>
  </ion-fab>
 </ion-content>
If you want the skeleton to look a bit more fancy you can give it different widths for example by adding this to your app/home/home.page.scss:
.fake-skeleton {
    width: 60%;
}
Now the home view of our Ionic Firebase Todolist is working but we need the second view so we can actually create todos!
Creating & Updating Firestore Documents
Our details view takes care of creating new todos and also updating existing todos. This means, we need to find out if we navigated to the page with the id of a document or without any information.
To do so, we use the Angular Router and the ActivatedRoute, especially the snapshot data of the current route. If we then got the id from the params, we call our loadTodo() function which will load only one specific document of our collection (through our TodoService).
You might have noticed that we also use our Todo interface along the code examples which adds nice typings to our objects!
Once we want to save our todo we need to check if we are updating an existing todo or add a todo – but in both cases we can use the appropriate function of our service. We also show a loading while performing our operations and because we use async/await for the promises, we need to mark the functions as async as well.
Now go ahead and change your app/pages/todo-details/todo-details.page.ts to:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import { Todo, TodoService } from './../../services/todo.service';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { NavController, LoadingController } from '@ionic/angular';
 @Component({
  selector: 'app-todo-details',
  templateUrl: './todo-details.page.html',
  styleUrls: ['./todo-details.page.scss'],
})
export class TodoDetailsPage implements OnInit {
   todo: Todo = {
    task: 'test',
    createdAt: new Date().getTime(),
    priority: 2
  };
   todoId = null;
   constructor(private route: ActivatedRoute, private nav: NavController, private todoService: TodoService, private loadingController: LoadingController) { }
   ngOnInit() {
    this.todoId = this.route.snapshot.params['id'];
    if (this.todoId)  {
      this.loadTodo();
    }
  }
   async loadTodo() {
    const loading = await this.loadingController.create({
      content: 'Loading Todo..'
    });
    await loading.present();
     this.todoService.getTodo(this.todoId).subscribe(res => {
      loading.dismiss();
      this.todo = res;
    });
  }
   async saveTodo() {
     const loading = await this.loadingController.create({
      content: 'Saving Todo..'
    });
    await loading.present();
     if (this.todoId) {
      this.todoService.updateTodo(this.todo, this.todoId).then(() => {
        loading.dismiss();
        this.nav.goBack('home');
      });
    } else {
      this.todoService.addTodo(this.todo).then(() => {
        loading.dismiss();
        this.nav.goBack('home');
      });
    }
  }
 }
Finally the last missing piece which might actually be the most boring of all snippets. We just need to input elements and connect them using ngModel. The result looks like this inside your app/pages/todo-details/todo-details.page.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<ion-header>
  <ion-toolbar color="primary">
    <ion-buttons slot="start">
      <ion-back-button defaultHref="/home"></ion-back-button>
    </ion-buttons>
    <ion-title>Details</ion-title>
  </ion-toolbar>
</ion-header>
 <ion-content padding>
  <ion-list lines="full">
    <ion-item>
      <ion-input required type="text" placeholder="Task" [(ngModel)]="todo.task"></ion-input>
    </ion-item>
    <ion-item>
      <ion-input required type="number" placeholder="Priority" [(ngModel)]="todo.priority"></ion-input>
    </ion-item>
  </ion-list>
  <ion-button expand="full" (click)="saveTodo()">Save</ion-button>
</ion-content>
Nothing special, but now your Ionic Firebase app is finished and you have all the basic operations in place to work with the Firestore database!
Conclusion
The Ionic 4 routing might be new but the connection to Firebase with AngularFire works just as good as always. Especially the environment that’s now available makes it easy to add different configurations in case you have multiple systems/projects for test/staging/prod.
You can also find a video version of this tutorial below.
youtube
Get the free 7 day Ionic 4 Crash Course to learn how to:
Get started with Ionic
Build a Tab Bar navigation
Make HTTP calls to a REST API
Store Data inside your app
Use Cordova plugins
Style your Ionic app
The course is free, so there's nothing you can lose!
Success! Now check your email to confirm your subscription.
via Devdactic https://ift.tt/2NLIRez
0 notes
ozzy432836 · 8 years ago
Text
A very scattered C# post
Reflection
Mutable - can change, immutable - cannot change string is immutable - you actually create a new string when you append etc StringBuilder is physically modified when you append so its cheaper on memory
For everything, research pros and cons
Angular + very declarative, you know what element is bound to what as its clear in markup -everything has ng- in jQuery, it uses CSS selectors and you may not always be clear what is going where... + Directive can manipulate the DOM
Incremental Database Backups
Automated Testing, Automated Deploying
Factory Pattern
Repository Pattern
Red Green Refactor
SOLID Principles: http://www.codeproject.com/Articles/703634/SOLID-architecture-principles-using-simple-Csharp
S rp Single Responsibility Principle - ensure your classes are used for single responsibilities e.g a class person can have methods to add, remove, update, delete people - however dont sneak things in there like SendEmail and hasAccessTo
O cp Open Closed Principle - once you have written a class and deployed it, dont make changes to it if a new feature is required - extend it instead
L sp Liskov Substitution Principle - Personalised Prospectus Application is not a student yet it is  just a lead - however it is saved to the database as a person -
I sp Interface Segragation Principle - similar to OCP - a good example is INEwsCollection which must implement getNewsCollection - if you decide that a new INewsCollection consumer needs a checkNewsCollection method - dont add the method to INewsCollection because you will have to implement in MoodleForumNewsCollection and TestNewsCollection - extend the INewsCollection with INewsCollectionVerifed and your new class should implement the INewsCollectionVerified
D ip Dependency Inversion Principle - IOC sits above:Service Locato, Events, Delegates and DI (Dependency Inversion OR Injection?) - have implemented by inverting control of which db connector to load to a DBConnector class - an early example https://onedrive.live.com/?cid=289FADB32C0AB5D3&id=289FADB32C0AB5D3%2138959 (demonstrates my thinking) - have implemented this using IOC for databases where you dont know which database you will need till runtime so I used polymorphism to call methods from the parent class yet I passed the child class in to call the method - however to really implement this, you combine with SRP and dont create different instances of the interface implementor when you get into your class, inject the Interface in through the constructor, method or property
http://prodinner.aspnetawesome.com/ ASP.NET MVC Ajax
Static Classes: Really just a bucket of methods (somewhere to store things that dont belong to objects). If you declare
fields/properties in here at class level then you must make them static to be accessible in a static method.
Abstract class: Model something in a type hierarchy e.g. Vehicle is abstract and all children must inherit it and implement its methods
(almost like an interface but you can code the methods or choose not to).
Polymorphism: A collection can only hold people. You can add an employee or a student...so long as it is derived from class people.
Overloading: Multiple methods, same name, different arguments.
Overriding: Multiple methods, same name, same arguments. Use in child to override parent method. Its the same as overriding in Java
except you have to use the keyword...
Virtual keyword on method: this revolves around overriding parent methods The virtual modifier tells the compiler that when any class derived from class A is used, an override method should be called. So the child should use the override keyword
virtual keyword on property
Indexer
Multi threading:
Race condition: Occurs in multithreading - when two threads access a shared variable at the same time. The first reads the var and the
second reads same value. They then both perform their operations on the value and they race to see which can update the value last.
Whichever thread writes last wins.
Deadlock - stalemate: two threads lock different variables then try to lock the variable that is already locked by the other thread. So they both wait till each other is free before continuing. Stalemate!
Struct: a lightweight class - use when you just want to structurally store a collection of objects. Its like new stdClass in PHP (but more organised). Its better than creating a dictionary and assigning kvps to store your lightweight collection as i have done in the past. They have limitations compared to classes and you would normally use a class. Classes are reference types while struct are value type objects. If passing a struct in place of an object, you must use the ref keyword to tell the method that the variable should be populated by reference and not value.. Only use if there is a specific need to pass an object by value and not reference.
Enum: you have a set of constants that will never change. e.g. sun - sat, jan - dec. You can declare these at namespace level so it can
be used by all classes. By default, the type of items in list are ints but these can be any primitive type except char
Delegate: used to treat a method like an object. I dont think it has any real use in the example I saw http://aspnetcentral.com/aspnet45/expert/video/0410%20Understand%20delegate%20methods.html
Fields: are basically what you thought were variables. These should be accessed via getters and setters because they abstract the  field and allow you to make change...tbc
Properties: are the way you declare variables in Models with the get; set; They expose fields
Using {} - use this whenever: The using statement is only useful for objects with a lifetime that does not extend beyond the method in which the objects are constructed. Remember that the objects you instantiate must implement the System.IDisposable interface. E.G SQLConnection
FluentValidation is an alternative to data annotations. Some feel it is easier to read and maintain. http://stackoverflow.com/questions/16678625/asp-net-mvc-4-ef5-unique-property-in-model-best-practice In the example i studied, it felt like writing unnecessary code e.g. making a field unique...
Boxing: int x = 1; object y = x; Unboxing: y = 1; x = (int)y; The above work with casting when unboxing and generalisation (almost polymorphism) when boxing
hash region: allow you to collape blocks of code in long code and add a description so you know what each region is for
hash pragma: use to disable warnings and reenable later on
Yield:
Technical Debt: When you make a change, there is often other changes to make in other parts to ensure the integrity of your application. These other changes are called debt.
Use of interfaces:
IDisposable: a way to dispose of unmanaged resources - used most for db connections and talking to db via EF. Use if you are directly accessing an unmanaged resource
IEnumerable vs ICollection
Repository pattern: Why?
Internal keyword vs private http://stackoverflow.com/questions/3813485/internal-vs-private-access-modifiers
IOC - passing the decision making away from the class to an external entity e.g. constructor should not decide which database type to instantiate. You can use DI to implement IOC. You can also use delegates, events, and service locators https://www.facebook.com/video.php?v=690253231015623
DI - Dependency Injection
Know your versions: Visual Studio: 2013 (v12) - help about ASP.NET: 4.5 - search targetFramework in web.config C# : 5 MVC: 5 - search system.data.mvc in web.config EF: 6 - search system.data.entity in web.config
0 notes
t-baba · 8 years ago
Photo
Tumblr media
Creating Strictly Typed Arrays and Collections in PHP
One of the language features announced back in PHP 5.6 was the addition of the ... token to denote that a function or method accepts a variable length of arguments.
Something I rarely see mentioned is that it’s possible to combine this feature with type hints to essentially create typed arrays.
For example, we could have a Movie class with a method to set an array of air dates that only accepts DateTimeImmutable objects:
<?php class Movie { private $dates = []; public function setAirDates(\DateTimeImmutable ...$dates) { $this->dates = $dates; } public function getAirDates() { return $this->dates; } }
We can now pass a variable number of separate DateTimeImmutable objects to the setAirDates() method:
<?php $movie = new Movie(); $movie->setAirDates( \DateTimeImmutable::createFromFormat('Y-m-d', '2017-01-28'), \DateTimeImmutable::createFromFormat('Y-m-d', '2017-02-22') );
If we were to pass something else than a DateTimeImmutable, a string for example, a fatal error would be thrown:
If we instead already had an array of DateTimeImmutable objects that we wanted to pass to setAirDates(), we could again use the ... token, but this time to unpack them:
<?php $dates = [ \DateTimeImmutable::createFromFormat('Y-m-d', '2017-01-28'), \DateTimeImmutable::createFromFormat('Y-m-d', '2017-02-22'), ]; $movie = new Movie(); $movie->setAirDates(...$dates);
If the array were to contain a value that is not of the expected type, we would still get the fatal error mentioned earlier.
Additionally, we can use scalar types the same way starting from PHP 7. For example, we can add a method to set a list of ratings as floats on our Movie class:
<?php declare(strict_types=1); class Movie { private $dates = []; private $ratings = []; public function setAirDates(\DateTimeImmutable ...$dates) { /* ... */ } public function getAirDates() : array { /* ... */ } public function setRatings(float ...$ratings) { $this->ratings = $ratings; } public function getAverageRating() : float { if (empty($this->ratings)) { return 0; } $total = 0; foreach ($this->ratings as $rating) { $total += $rating; } return $total / count($this->ratings); } }
Again, this ensures that the ratings property will always contain floats without us having to loop over all the contents to validate them. So now we can easily do some math operations on them in getAverageRating(), without having to worry about invalid types.
Problems with This Kind of Typed Arrays
One of the downsides of using this feature as typed arrays is that we can only define one such array per method. Let’s say we wanted to have a Movie class that expects a list of air dates together with a list of ratings in the constructor, instead of setting them later via optional methods. This would be impossible with the method used above.
Another problem is that when using PHP 7, the return types of our get() methods would still have to be “array”, which is often too generic.
Solution: Collection Classes
To fix both problems, we can simply inject our typed arrays inside so-called “collection” classes. This also improves our separation of concerns, because we can now move the calculation method for the average rating to the relevant collection class:
<?php declare(strict_types=1); class Ratings { private $ratings; public function __construct(float ...$ratings) { $this->ratings = $ratings; } public function getAverage() : float { if (empty($this->ratings)) { return 0; } $total = 0; foreach ($this->ratings as $rating) { $total += $rating; } return $total / count($this->ratings); } }
Notice how we’re still using a list of typed arguments with a variable length in our constructor, which saves us the trouble of looping over each rating to check its type.
Continue reading %Creating Strictly Typed Arrays and Collections in PHP%
by Bert Ramakers via SitePoint http://ift.tt/2oehxoH
0 notes