Wednesday, July 09, 2008

Type-safe Builder Pattern in Scala

The Builder Pattern is an increasingly popular idiom for object creation. Traditionally, one of it's shortcomings in relation to simple constructors is that clients can try to build incomplete objects, by omitting mandatory parameters, and that error will only show up in runtime. I'll show how to make this verification statically in Scala.


So, let's say you want to order a shot of scotch. You'll need to ask for a few things: the brand of the whiskey, how it should be prepared (neat, on the rocks or with water) and if you want it doubled. Unless, of course, you are a pretentious snob, in that case you'll probably also ask for a specific kind of glass, brand and temperature of the water and who knows what else. Limiting the snobbery to the kind of glass, here is one way to represent the order in scala.
sealed abstract class Preparation  /* This is one way of coding enum-like things in scala */
case object Neat extends Preparation
case object OnTheRocks extends Preparation
case object WithWater extends Preparation

sealed abstract class Glass
case object Short extends Glass
case object Tall extends Glass
case object Tulip extends Glass

case class OrderOfScotch(val brand:String, val mode:Preparation, val isDouble:Boolean, val glass:Option[Glass])

A client can instantiate their orders like this:
val normal = new OrderOfScotch("Bobby Runner", OnTheRocks, false, None)
val snooty = new OrderOfScotch("Glenfoobar", WithWater, false, Option(Tulip));

Note that if the client doesn't want to specify the glass he can pass None as an argument, since the parameter was declared as Option[Glass]. This isn't so bad, but it can get annoying to remember the position of each argument, specially if many are optional. There are two traditional ways to circumvent this problem — define telescoping constructors or set the values post-instantiation with accessors — but both idioms have their shortcomings. Recently, in Java circles, it has become popular to use a variant of the GoF Builder pattern. So popular that it is Item 2 in the second edition of Joshua Bloch's Effective Java. A Java-ish implementation in Scala would be something like this:
class ScotchBuilder {
private var theBrand:Option[String] = None
private var theMode:Option[Preparation] = None
private var theDoubleStatus:Option[Boolean] = None
private var theGlass:Option[Glass] = None

def withBrand(b:Brand) = {theBrand = Some(b); this} /* returning this to enable method chaining. */
def withMode(p:Preparation) = {theMode = Some(p); this}
def isDouble(b:Boolean) = {theDoubleStatus = some(b); this}
def withGlass(g:Glass) = {theGlass = Some(g); this}

def build() = new OrderOfScotch(theBrand.get, theMode.get, theDoubleStatus.get, theGlass);
}

This is almost self-explanatory, the only caveat is that verifying the presence of non-optional parameters (everything but the glass) is done by the Option.get method. If a field is still None, an exception will be thrown. Keep this in mind, we'll come back to it later.

The var keyword prefixing the fields means that they are mutable references. Indeed, we mutate them in each of the building methods. We can make it more functional in the traditional way:
object BuilderPattern {
class ScotchBuilder(theBrand:Option[String], theMode:Option[Preparation], theDoubleStatus:Option[Boolean], theGlass:Option[Glass]) {
def withBrand(b:String) = new ScotchBuilder(Some(b), theMode, theDoubleStatus, theGlass)
def withMode(p:Preparation) = new ScotchBuilder(theBrand, Some(p), theDoubleStatus, theGlass)
def isDouble(b:Boolean) = new ScotchBuilder(theBrand, theMode, Some(b), theGlass)
def withGlass(g:Glass) = new ScotchBuilder(theBrand, theMode, theDoubleStatus, Some(g))

def build() = new OrderOfScotch(theBrand.get, theMode.get, theDoubleStatus.get, theGlass);
}

def builder = new ScotchBuilder(None, None, None, None)
}

The scotch builder is now enclosed in an object, this is standard practice in Scala to isolate modules. In this enclosing object we also find a factory method for the builder, which should be called like so:
import BuilderPattern._

val order = builder withBrand("Takes") isDouble(true) withGlass(Tall) withMode(OnTheRocks) build()

Looking back at the ScotchBuilder class and it's implementation, it might seem that we just moved the huge constructor mess from one place (clients) to another (the builder). And yes, that is exactly what we did. I guess that is the very definition of encapsulation, sweeping the dirt under the rug and keeping the rug well hidden. On the other hand, we haven't gained all the much from this "functionalization" of our builder; the main failure mode is still present. That is, having clients forget to set mandatory information, which is a particular concern since we obviously can't fully trust the sobriety of said clients*. Ideally the type system would prevent this problem, refusing to typecheck a call to build() when any of the non-optional fields aren't set. That's what we are going to do now.

One technique, which is very common in Java fluent interfaces, would be to write an interface for each intermediate state containing only applicable methods. So we would begin with an interface VoidBuilder having all our withFoo() methods but no build() method, and a call to, say, withMode() would return another interface (maybe BuilderWithMode), and so on, until we call the last withBar() for a mandatory Bar, which would return an interface that finally has the build() method. This technique works, but it requires a metric buttload of code — for n mandatory fields 2n interfaces should be created. This could be automated via code generation, but there is no need for such heroic efforts, we can make the typesystem work in our favor by applying some generics magic. First, we define two abstract classes:
abstract class TRUE
abstract class FALSE

Then, for each mandatory field, we add to our builder a generic parameter:
class ScotchBuilder[HB, HM, HD](val theBrand:Option[String], val theMode:Option[Preparation], val theDoubleStatus:Option[Boolean], val theGlass:Option[Glass]) {

/* ... body of the scotch builder .... */

}

Next, have each withFoo method pass ScotchBuilder's type parameters as type arguments to the builders they return. But, and here is where the magic happens, there is a twist on the methods for mandatory parameters: they should, for their respective generic parameters, pass instead TRUE:
class ScotchBuilder[HB, HM, HD](val theBrand:Option[String], val theMode:Option[Preparation], val theDoubleStatus:Option[Boolean], val theGlass:Option[Glass]) {
def withBrand(b:String) =
new ScotchBuilder[TRUE, HM, HD](Some(b), theMode, theDoubleStatus, theGlass)

def withMode(p:Preparation) =
new ScotchBuilder[HB, TRUE, HD](theBrand, Some(p), theDoubleStatus, theGlass)

def isDouble(b:Boolean) =
new ScotchBuilder[HB, HM, TRUE](theBrand, theMode, Some(b), theGlass)

def withGlass(g:Glass) =
new ScotchBuilder[HB, HM, HD](theBrand, theMode, theDoubleStatus, Some(g))
}

The second part of the magic act is to apply the world famous pimp-my-library idiom and move the build() method to an implicitly created class, which will be anonymous for the sake of simplicity:
implicit def enableBuild(builder:ScotchBuilder[TRUE, TRUE, TRUE]) = new {
def build() =
new OrderOfScotch(builder.theBrand.get, builder.theMode.get, builder.theDoubleStatus.get, builder.theGlass);
}

Note the type of the parameter for this implicit method: ScotchBuilder[TRUE, TRUE, TRUE]. This is the point where we "declare" that we can only build an object if all the mandatory parameters are specified. And it really works:
scala> builder withBrand("hi") isDouble(false) withGlass(Tall) withMode(Neat) build()
res5: BuilderPattern.OrderOfScotch = OrderOfScotch(hi,Neat,false,Some(Tall))

scala> builder withBrand("hi") isDouble(false) withGlass(Tall) build()
<console>:9: error: value build is not a member of BuilderPattern.ScotchBuilder[BuilderPattern.TRUE,BuilderPattern.FALSE,BuilderPattern.TRUE]
builder withBrand("hi") isDouble(false) withGlass(Tall) build()

So, we achieved our goal (see the full listing below). If you are worried about the enormous parameter lists inside the builder, I've posted here an alternative implementation with abstract members instead. It is more verbose, but also cleaner.

Now, remember those abstract classes TRUE and FALSE? We never did subclass or instantiate them at any point. If I'm not mistaken, this is an idiom named Phantom Types, commonly used in the ML family of programming languages. Even though this application of phantom types is fairly trivial, we can glimpse at the power of the mechanism. We have, in fact, codified all 2n states (one for each combination of mandatory fields) as types. ScotchBuilder's subtyping relation forms a lattice structure and the enableBuild() implicit method requires the supremum of the poset (namely, ScotchBuilder[TRUE, TRUE, TRUE]). If the domain requires, we could specify any other point in the lattice — say we can doll-out a dose of any cheap whiskey if the brand is not given, this point is represented by ScotchBuilder[_, TRUE, TRUE]. And we can even escape the lattice structure by using Scala inheritance. Of course, I didn't invent any of this; the idea came to me in this article by Matthew Fluet and Riccardo Pucella, where they use phantom types to encode subtyping in a language that lacks it.



object BuilderPattern {
sealed abstract class Preparation
case object Neat extends Preparation
case object OnTheRocks extends Preparation
case object WithWater extends Preparation

sealed abstract class Glass
case object Short extends Glass
case object Tall extends Glass
case object Tulip extends Glass

case class OrderOfScotch(val brand:String, val mode:Preparation, val isDouble:Boolean, val glass:Option[Glass])

abstract class TRUE
abstract class FALSE

class ScotchBuilder
[HB, HM, HD]
(val theBrand:Option[String], val theMode:Option[Preparation], val theDoubleStatus:Option[Boolean], val theGlass:Option[Glass]) {
def withBrand(b:String) =
new ScotchBuilder[TRUE, HM, HD](Some(b), theMode, theDoubleStatus, theGlass)

def withMode(p:Preparation) =
new ScotchBuilder[HB, TRUE, HD](theBrand, Some(p), theDoubleStatus, theGlass)

def isDouble(b:Boolean) =
new ScotchBuilder[HB, HM, TRUE](theBrand, theMode, Some(b), theGlass)

def withGlass(g:Glass) = new ScotchBuilder[HB, HM, HD](theBrand, theMode, theDoubleStatus, Some(g))
}

implicit def enableBuild(builder:ScotchBuilder[TRUE, TRUE, TRUE]) = new {
def build() =
new OrderOfScotch(builder.theBrand.get, builder.theMode.get, builder.theDoubleStatus.get, builder.theGlass);
}

def builder = new ScotchBuilder[FALSE, FALSE, FALSE](None, None, None, None)
}



* Did you hear that noise? It's the sound of my metaphor shattering into a million pieces



EDIT 2008-07-09 at 19h00min: Added introductory paragraph.

1,001 comments:

«Oldest   ‹Older   601 – 800 of 1001   Newer›   Newest»
s said...


Plastic Corrugated Sheet - Corpac is India’s No.1 Plastic Corrugated Sheets & Box Manufacturer, suppliers in Qatar, New Zealand, Germany, Philippines, UK and Spain.

Data Science Training in Bangalore said...

Very good message. I stumbled across your blog and wanted to say that I really enjoyed reading your articles. Anyway, I will subscribe to your feed and hope you post again soon.

Business Analytics Course

Techinstitute said...

I wanted to leave a little comment to support you and wish you the best of luck. We wish you the best of luck in all of your blogging endeavors.

Data Analytics Course in Bangalore

Data Science Course in Bangalore said...

Actually I read it yesterday I looked at most of your posts but I had some ideas about it . This article is probably where I got the most useful information for my research and today I wanted to read it again because it is so well written.
Data Science Course in Bangalore

Petersons said...

Thanks for the update you have nicely covered this topic. keep it up


Gloss Garage Doors

360DigiTMGNoida said...

This Blog is very useful and informative.
data scientist course in noida

360digitmgdelhi said...

I read that Post and got it fine and informative. Please share more like that...
data science course delhi

stock market expert in delhi said...

Lakshay consultant is known for giving best services to there clients with full of honesty and dignity . Lakshay consultancy deals in Equities, Currencies, Commodities, IPOs, Stock Market Expert in Delhi , Bonds/NCDs through NSE, BSE, MCXSX, USE. Depository services through NSDL and CDSL.

arshiya said...

I enjoyed reading your article. Thanks for taking the time to post such a valuable article.
seo content writing tips
language similar to english
salesforce basics
star certification
hacking books
interview questions on tableau

Rick said...

Excellent, and thanks for sharing this.

Rick Anderson

Petersons said...

Cool blog you got here and thank you for the valuable info.


garage door repair

R ADK said...

Organic Chemistry tutor
Organic chemistry
online tutor

360DigiTMG said...

This is a great motivational article. In fact, I am happy with your good work. They publish very supportive data, really. Continue. Continue blogging. Hope you explore your next post
data scientist malaysia

Petersons said...

This is really great news. Thank you for sharing it with us!


garage door blog

Micky john said...

Your service is really cool.
e-learning

Petersons said...

This is a brilliant writing and very pleased to find this site. I couldn’t discover to much different information on your blog. I will surely be back again to look at some other important posts that you have in future.


garage door repair Guelph

shakthi said...

digital marketing company in chennai, seo company in chennai, ecommerce website development company in chennai

Nictcspbc said...


Thank you for sharing such a great information. Here NICTCSPBC is the best service provider of SBI Kiosk Banking in India which provides the best services of Kiosk Banking at reliable prices to their customers.

Csp registration
Csp apply

Unknown said...

You got a really useful blog I have been here reading for about half an hour. I am a newbie and your post is valuable for me.


garage door repair Scarborough 

Tech Institute said...

Fantastic blog with excellent information and valuable content just added your blog to my bookmarking sites thank for sharing.
Data Science Course in Chennai

Tech said...

I really enjoy every part and have bookmarked you to see the new things you post. Well done for this excellent article. Please keep this work of the same quality.
Artificial Intelligence course in Chennai

madhu said...

Hi guys, here we are servicing all home appliances brands .we is servicing to here. Like washing machine, refrigerator, air conditioner, microwave oven, the coolers are accessible in essentially three sorts they resemble. Whirlpool Washing machine Service Center in Neral Single door, double door entryway and one next to the other entryway coolers. The new age ridges are accompanying some incredible choices like. Convertible alternatives this is perhaps the main innovation in the coolers. Whirlpool Washing machine Service Center in Chunabhatti Also, the clothes washer is perhaps the best item at present days. Whirlpool Washing machine Service Center in Tilak Nagar The clothes washers will wash the materials rapidly and clothes washers will eliminate the actual pressure of the clients.

madhu said...

Single drum will only provide washing process and dual drum will provide the washing process along with draining function. Whirlpool Washing machine Service Center in ChemburThe single drum will occupies very less space to store comparing to double drum washing machines the new clothes washers are updated with many progressed washing highlights. Whirlpool Washing Machine Service Center in Mira RoadThe utilization of the climate control systems are mostly increments in summer seasons. Whirlpool Washing machine Service Center in KandivaliSince climate control systems are use for take just cool air. What's more, these forced air systems can run for quite a long time with no issue and this

madhu said...

will gives its service the microwave gives any issues microwave not warming is a typical issue. Whirlpool Washing machine Service Center in MaladThis duct AC has the best capacity of cooling so this will provide the fast cooling to the room. Whirlpool Washing Machine Service Center in MulundThese air conditioners are one of the great appliances in this generation and the air conditioners will requires a good maintenanceWhirlpool Washing machine Service Center Jogeshwari So these air conditioners will need a best servicing to run it properly. Home-appliances repair our professionals accomplished to in this documented. Whirlpool Washing Machine Service Center in Dombivli They are accomplished and they are providing for you best support of your item.

madhu said...

Subterranean insect sort of issue they will tackier of it they have colossal information to take care of the issue. Whirlpool Refrigerator Service Center in MankhurdFurthermore, we are giving best proposals to you on month general assistance guarantee and multi month service guarantee to your items. Whirlpool Refrigerator Service Center in Vashi We are giving every minute of every day hour’s service to the clients. Best help and poor clients will fulfill with our service. Whirlpool Refrigerator Service Center in Churchgate One of the best services to the customers. Our supervisory group has over 10 years of involvement service suppliers; we are consistently offers the best types of assistance to the customers. Whirlpool Refrigerator Service Center in Marine LinesWith the best specialized unit we help to tackle the any major and minor fixes in the item. And we take the all safety measures of covid-19. And our technicians will give to you best services to your products.

Michael Oliver said...

Good post,

Digital Marketing Companies in Chennai, Website Design Companies in Chennai, SEO Companies in Chennai, Digital Marketing Company Chennai, Web Design Company Chennai.

https://www.wisewebtek.com

Petersons said...

חשבתי שאתקל בסתם עוד מאמר שטחי. כמובן שטעיתי.

פוליש קריסטל

Micky john said...

Good post. Thank you for sharing this with us.
News For Finance

Nisha said...

Website Development Services In Delhi
Web Cloud Technology offers world class web development services in Delhi, India. We promise to take care of all your website development needs by providing high end and modern solutions that are inventive and profitable.

For more information visit on:-
https://webcloudtechnologies.com/

Nisha said...

Website Development Services In Delhi
Web Cloud Technology offers world-class web development services in Delhi, India. We promise to take care of all your website development needs by providing high-end and modern solutions that are inventive and profitable.

For more information visit on:-
https://webcloudtechnologies.com/

Data Science Training in Hyderabad said...

Fantastic Site with useful and unique content looking forward to the next update thank you.
Data Science Training in Hyderabad

David Smith said...

Good writing...keep posting dear friend

אטרקציות לבר מצווה

Data Science Institute Bangalore said...

It's very educational and well-written content for a change. It's good to see that some people still understand how to write a great article!
Data Science Institute in Bangalore

Data Analytics Courses in Bangalore said...

This is just the information I find everywhere. Thank you for your blog, I just subscribed to your blog. It's a good blog.

Data Analytics Courses in Bangalore

Tech said...

I really enjoy every part and have bookmarked you to see the new things you post. Well done for this excellent article. Please keep this work of the same quality.
Artificial Intelligence course in Chennai

Data Science in Pune said...

You can comment on the blog ordering system. You should discuss, it's splendid. Auditing your blog would increase the number of visitors. I was very happy to find this site. Thank you...

Data Science Classes in Pune

Jack Harry said...

I am looking for the informative post thanks for share it.
Finance Reports 24/7

Data Science Training said...

Excellent site with great content and very informative. I would like to thank you for the efforts you have made in writing.
Data Science Training in Bangalore

Best Data Science Courses said...

This is an excellent article. I like this topic. This site has many advantages. I have found a lot of interesting things on this site. It helps me in so many ways. Thanks for posting this again.

Best Data Science Courses in Bangalore

Data Science Training in Bangalore said...

I really enjoyed reading your blog. It was very well written and easy to understand. Unlike other blogs that I have read which are actually not very good. Thank you so much!

Data Science Training in Bangalore

Unknown said...

אני לא מסכים עם כל מה שכתוב, אבל מאמר מעניין מאוד

דוכני מזון לאירועים 

Data Analytics Courses in Bangalore said...

Very good message. I stumbled across your blog and wanted to say that I really enjoyed reading your articles. Anyway, I will subscribe to your feed and hope you post again soon.

Data Analytics Courses in Bangalore

Data Science in Bangalore said...

A good blog always contains new and exciting information and as I read it I felt that this blog really has all of these qualities that make a blog.

Data Science In Bangalore

Data Science in Pune said...

I enjoyed the coursework, the presentations, the classmates and the teachers. And because my company reimbursed 100% of the tuition, the only cost I had to pay on my own was for books and supplies. Otherwise, I received a free master's degree. All I had to invest was my time.
Data Science Training in Pune

Jack Harry said...

Nice content
greenairductcleaningpittsburgh.com

Data Science Institutes in Bangalore said...

Really impressed! Everything is a very open and very clear clarification of the issues. It contains truly facts. Your website is very valuable. Thanks for sharing.

Business Analytics Course in Bangalore

Unknown said...

I was very pleased to find this site.I wanted to thank you for this great read!! I definitely enjoying every little bit of it and I have you bookmarked to check out new stuff you post.


commercial hood cleaning pittsburgh 

David Smith said...

This is a really good read for me, Must admit that you are one of the best bloggers I ever saw.Thanks for posting this informative article.

garage door repair in Evergreen

Data Science Institutes in Bangalore said...

I'm glad I found this blog! Occasionally, students want to know the keys to writing productive literary essays. Your first-class knowledge of this great job can become a suitable foundation for these people. Good

Data Science Institutes in Bangalore

Tech said...

I really enjoy every part and have bookmarked you to see the new things you post. Well done for this excellent article. Please keep this work of the same quality.
Artificial Intelligence course in Chennai

Tech Science said...

Fantastic blog with excellent information and valuable content just added your blog to my bookmarking sites thank for sharing.
Data Science Course in Chennai

Jack Harry said...

This amazing post impressed me
garage door repair in pittsburgh

Business said...

Nice Information. Thanks for sharing. Reach us For the same,
WEB Technologies,
IMAGE Editing Services,
LEATHER Products.

SARA said...

Nice Information. Thanks for sharing. Reach Our Services

Data Science Bangalore said...

I really enjoy reading all of your blogs. It is very helpful and very informative and I really learned a lot from it. Definitely a great article
Data Science Course Bangalore

Micky john said...

informative post
garage door installation burlington

Micky john said...

This amazing post impressed me
Cleveland Plumbing Guy

Data Science Training in Hyderabad said...

Fantastic Site with useful and unique content looking forward to the next update thank you.
Data Science Training in Hyderabad

Data Analytics Courses in Bangalore said...

You actually make it seem like it's really easy with your acting, but I think it's something I think I would never understand. I find that too complicated and extremely broad. I look forward to your next message. I'll try to figure it out!
Data Analytics Courses in Bangalore

Data Science Training said...

Excellent site with great content and very informative. I would like to thank you for the efforts you have made in writing.
Data Science Training in Bangalore

Data Science in Bangalore said...

Very informative message! There is so much information here that can help any business get started with a successful social media campaign!
Data Science In Bangalore

Micky john said...

It is very fantastic article , Thanks for sharing .
best essay writing service reddit

Data Science Institute Bangalore said...

I was very happy to find this site. I wanted to thank you for this excellent reading !! I really enjoy every part and have bookmarked you to see the new things you post.

Data Science Institute in Bangalore

Data Science Bangalore said...

I really enjoy reading all of your blogs. It is very helpful and very informative and I really learned a lot from it. Definitely a great article
Data Science Course Bangalore

Data Science in Bangalore said...

Very good message. I stumbled across your blog and wanted to say that I really enjoyed reading your articles. Anyway, I will subscribe to your feed and hope you post again soon.

Data Science In Bangalore

Data Science Institute Bangalore said...

I am very happy to have seen your website and hope you have so many entertaining times reading here. Thanks again for all the details.
Data Science Institute in Bangalore

Data Analytics Courses in Bangalore said...

I am delighted to discover this page. I must thank you for the time you devoted to this particularly fantastic reading !! I really liked each part very much and also bookmarked you to see new information on your site.
Data Analytics Courses in Bangalore

Data Science in Pune said...

I enjoyed the coursework, the presentations, the classmates and the teachers. And because my company reimbursed 100% of the tuition, the only cost I had to pay on my own was for books and supplies. Otherwise, I received a free master's degree. All I had to invest was my time.
Data Science Training in Pune

Micky john said...

A very awesome blog post. We are really grateful for your blog post. You will find a lot of approaches after visiting your post.
Cleveland Garage Door Pros

Micky john said...

It's always exciting to read articles from other writers and practice something from their websites.
Green Air Duct Cleaning

Micky john said...

חשבתי שאתקל בסתם עוד מאמר שטחי. כמובן שטעיתי.
פיתוח אפליקציות לאנדרואיד

Indo Routes said...

Hey, I like this and its helpful for me and i appreciate your work. Thanks for sharing nice info. Golden Triangle Tour Package India

Indo Routes said...

Thanks for sharing the info, keep up the good work going.... I really enjoyed exploring your site. Golden Triangle Tour Package India

Custom CBD packaging said...

CBD oils are herbal extracts and an active ingredient. It’s 40% extract directly from a plant. So don’t you think this health care source needs it’s packaging that store its natural ingredients? Regarding this, your answer would be a Yes! Its packaging should be as safe as the product. This would reflect its instincts to buyers. So, we offer you the best quality Custom CBD packaging boxes with limitless choices. This medical product needs to be stored in a non-toxic packaging to be delivered to our clients.

Leather Net Shop said...

I am very thankful for share this post. Buy real leather jackets with worldwide free shipping.
Harley Davidson Jackets
Superhero Leather Jackets
Aviator Leather Jacket
Motogp Leather Jacket

Knowledge said...

Thank a lot. You have done excellent job. I enjoyed your blog . Nice efforts
Cyber Security Course in Bangalore

Emerging Technologies said...

Nice Blog and i would like to thank for the efforts you have made in writing this post, hoping the same best work from you in the future as well. Thanks for sharing. Great websites!
Tableau Training in Bangalore

Institute said...

Such a very useful article and very interesting to read this article, i would like to thank you for the efforts you had made for writing this awesome article. Thank you!
Python Training in Bangalore

Micky john said...

It's always exciting to read articles from other writers and practice something from their websites.
garage door installation burlington

SNK Social Fame said...

I am so happy to have found your blog! Your article looks beautiful! The information you have shared is very informative. thanks Buy Instagram Followers India

vé máy bay từ canada về Việt Nam said...

Aivivu đại lý vé máy bay, tham khảo

vé máy bay đi Mỹ bao nhiêu tiền

mua vé máy bay từ hàn quốc về việt nam

vé bay nha trang sai gon

vé máy bay phú quốc hà nội

vé máy bay eva từ mỹ về việt nam

Data Science Training said...

Excellent site with great content and very informative. I would like to thank you for the efforts you have made in writing.
Data Science Training in Bangalore

Nino Nurmadi , S.Kom said...

Nino Nurmadi, S.Kom
Nino Nurmadi, S.Kom
Nino Nurmadi, S.Kom
Nino Nurmadi, S.Kom
Nino Nurmadi, S.Kom
Nino Nurmadi, S.Kom
Nino Nurmadi, S.Kom
Nino Nurmadi, S.Kom
Nino Nurmadi, S.Kom
Nino Nurmadi, S.Kom

Jackets In Leather said...

I am looking for the informative post thanks for share it.
I have an online store for leather garments with the name of Jackets In Leather.

AI course in pune said...

I am really enjoying reading your well written articles. It looks like you spend a lot of effort and time on your blog. I have bookmarked it and I am looking forward to reading new articles. Keep up the good work.
artificial intelligence course in pune

AI course in pune said...

I am really enjoying reading your well written articles. It looks like you spend a lot of effort and time on your blog. I have bookmarked it and I am looking forward to reading new articles. Keep up the good work.
artificial intelligence course in pune

Data Analytics Courses in Bangalore said...

I will very much appreciate the writer's choice for choosing this excellent article suitable for my topic. Here is a detailed description of the topic of the article that helped me the most.

Data Analytics Courses in Bangalore

Data Science in Bangalore said...

This is my first time visiting here. I found a lot of funny things on your blog, especially your discussion. From the tons of comments on your posts, I guess I'm not the only one who has all the free time here. Keep up the good work. I was planning to write something like this on my website and you gave me an idea.

Data Science In Bangalore

Data Science Training in Hyderabad said...

Fantastic Site with useful and unique content looking forward to the next update thank you.
Data Science Training in Hyderabad

Data Science Training in Hyderabad said...

Fantastic Site with useful and unique content looking forward to the next update thank you.
Data Science Training in Hyderabad

AI course in pune said...

I am really enjoying reading your well written articles. It looks like you spend a lot of effort and time on your blog. I have bookmarked it and I am looking forward to reading new articles. Keep up the good work.
artificial intelligence course in pune

Data Science Training said...

Excellent site with great content and very informative. I would like to thank you for the efforts you have made in writing.
Data Science Training in Bangalore

Data Science Institute Bangalore said...

It's like you understand the topic well, but forgot to include your readers. Maybe you should think about it from several angles.
Data Science Certification in Bangalore

Emerging Technologies said...

I need to thank you for this very good read and i have bookmarked to check out new things from your post. Thank you very much for sharing such a useful article and will definitely saved and revisit your site.
Data Science Course

Institute said...

Wow, happy to see this awesome post. I hope this think help any newbie for their awesome work and by the way thanks for share this awesomeness, i thought this was a pretty interesting read when it comes to this topic. Thank you..
Artificial Intelligence Course

Tech said...

I really enjoy every part and have bookmarked you to see the new things you post. Well done for this excellent article. Please keep this work of the same quality.
Artificial Intelligence course in Chennai

Knowledge said...

Thank a lot. You have done excellent job. I enjoyed your blog . Nice efforts
Cyber Security Course in Bangalore

Education said...

Your site is truly cool and this is an extraordinary moving article and If it's not too much trouble share more like that. Thank You..
Digital Marketing Institute in Bangalore

Digital Chandu said...

Very well written post. I have read the content and it is so helpful.Thanks for sharing.

Affiliate Marketing Training In Telugu
Affiliate Marketing Means In Telugu
Digital Marketing Training In Telugu
Blogging In Telugu
Podcast Meaning In telugu
SEO Meaning In Telugu
1000 Social BookMarking Sites List
Digital Marketing Course Training In Hyderabad

Data Science in Pune said...

It fully emerged to crown Singapore's southern shores and has undoubtedly put it on the world residential monument map. Still, I scored more points than I have in one season for GS. I think it would be hard to find someone with the same consistency that I have had over the years, so I'm happy.
Data Course Training in Pune

Business Analytics Course said...

I am a new user of this site, so here I saw several articles and posts published on this site, I am more interested in some of them, hope you will provide more information on these topics in your next articles.
Business Analytics Course

Best Data Science Courses in Bangalore said...

Now is the perfect time to plan for the future and now is the time to be happy. I have read this article and if I can I would like to suggest some cool tips or advice. Perhaps you could write future articles that reference this article. I want to know more!
Best Data Science Courses in Bangalore

Data Science in Pune said...

I am sure it will help many people. Keep up the good work. It's very compelling and I enjoyed browsing the entire blog.
Data Science Course in Pune

Data Analytics Course in Bangalore said...

A good blog always contains new and exciting information and as I read it I felt that this blog really has all of these qualities that make a blog.
Data Analytics Course in Bangalore

Digital Marketing Course in Bangalore said...

I found Habit to be a transparent site, a social hub that is a conglomerate of buyers and sellers willing to offer digital advice online at a decent cost.
Digital Marketing Course in Bangalore

Data Science in Pune said...

I have voiced some of the posts on your website now, and I really like your blogging style. I added it to my list of favorite blogging sites and will be back soon ...
Data Science Training in Pune

Business Analytics Course said...

They are produced by high level developers who will stand out for the creation of their polo dress. You will find Ron Lauren polo shirts in an exclusive range which includes private lessons for men and women.
Business Analytics Course

Best Data Science Courses in Bangalore said...

I am sure it will help many people. Keep up the good work. It's very compelling and I enjoyed browsing the entire blog.
Best Data Science Courses in Bangalore

Digital Marketing Course in Bangalore said...

You actually make it seem like it's really easy with your acting, but I think it's something I think I would never understand. I find that too complicated and extremely broad. I look forward to your next message. I'll try to figure it out!

Digital Marketing Course in Bangalore

Data Analytics Course in Bangalore said...

I always search online for articles that can help me. Obviously, there is a lot to know about this. I think you made a few good points about the features as well. Keep up the good work!

Data Analytics Course in Bangalore

Data Analytics Course in Bangalore said...

I am delighted to discover this page. I must thank you for the time you devoted to this particularly fantastic reading !! I really liked each part very much and also bookmarked you to see new information on your site.
Data Analytics Course in Bangalore

vivikhapnoi said...

It's really amazing to have many lists of will help to make thanks a lot for sharing
vé máy bay vietjet đi phú yên

lich bay tu tphcm di singapore

săn vé 0 đồng đi thái lan 2020

vé máy bay giá rẻ đi malaysia

báo giá vé máy bay đi úc

vé máy bay đi hàn quốc jetstar

Jackets In Leather said...

Thanks for share this helpful post. We have an online store of leather jackets. We are offering worldwide free shipping on every order.
BLACK LEATHER JACKET
FLYING JACKETS
LEATHER BOMBER JACKET
SHEARLING JACKETS

online reputation said...

This is my first-time visit to your blog and I am very interested in the articles that you serve. Provide enough knowledge for me.
commercial garage door repair dallas

Jackets In Leather said...

Thanks for share this helpful post. We have an online store of leather jackets. We are offering worldwide free shipping on every order.
BLACK LEATHER JACKET
FLYING JACKETS
LEATHER BOMBER JACKET
SHEARLING JACKETS

Jackets In Leather said...

Thanks for share this helpful post. We have an online store of leather jackets. We are offering worldwide free shipping on every order.
BLACK LEATHER JACKET
FLYING JACKETS
LEATHER BOMBER JACKET
SHEARLING JACKETS

Data Analytics Course in Bangalore said...

They are produced by high level developers who will stand out for the creation of their polo dress. You will find Ron Lauren polo shirts in an exclusive range which includes private lessons for men and women.
Data Analytics Course in Bangalore

Data Analytics Course in Bangalore said...

It is late to find this act. At least one should be familiar with the fact that such events exist. I agree with your blog and will come back to inspect it further in the future, so keep your performance going.

Data Analytics Course in Bangalore

Rohan Singh said...

Amazing!! Your will rock the reader community, the info is very engaging. You can collaborate to know more and explore the IT world with top mobile app Development Company. kotlin application development company. You can email us at sales@appsquadz.com or call us at +91-9717270746

Business Analytics Course said...

A good blog always contains new and exciting information and as I read it I felt that this blog really has all of these qualities that make a blog.
Business Analytics Course

Business Analytics Course said...

I wanted to leave a little comment to support you and wish you the best of luck. We wish you the best of luck in all of your blogging endeavors.
Business Analytics Course

Best Data Science Courses in Bangalore said...

very happy to find a good place for many here in the post, the writing is just great, thanks for the post.

Best Data Science Courses in Bangalore

Data Analytics Course in Bangalore said...

You can comment on the blog ordering system. You should discuss, it's splendid. Auditing your blog would increase the number of visitors. I was very happy to find this site. Thank you...
Data Analytics Course in Bangalore

Business Analytics Course said...

They are produced by high level developers who will stand out for the creation of their polo dress. You will find Ron Lauren polo shirts in an exclusive range which includes private lessons for men and women.
Business Analytics Course

Best Data Science Courses in Bangalore said...

I bookmarked your website because this site contains valuable information. I am very satisfied with the quality and the presentation of the articles. Thank you so much for saving great things. I am very grateful for this site.
Best Data Science Courses in Bangalore

Best Data Science Courses in Bangalore said...

You actually make it seem like it's really easy with your acting, but I think it's something I think I would never understand. I find that too complicated and extremely broad. I look forward to your next message. I'll try to figure it out!
Best Data Science Courses in Bangalore

Digital Marketing Course in Bangalore said...

First of all, you have a great blog. I will be interested in more similar topics. I see you have some very useful topics, I will always check your blog thank you.
Digital Marketing Course in Bangalore

Data Analytics Course in Bangalore said...

I will be interested in more similar topics. I see you have some really very useful topics, I will always check your blog thank you.

Data Analytics Course in Bangalore

Data Science said...

I am glad to discover this page. I have to thank you for the time I spent on this especially great reading !! I really liked each part and also bookmarked you for new information on your site.
Data Science Training in Chennai

Data Analytics Course said...

Excellent Blog! I would like to thank you for the efforts you have made in writing this post. Gained lots of knowledge.
Data Analytics Course

Data Science Courses said...

Awesome article. I enjoyed reading your articles. this can be really a good scan for me. wanting forward to reading new articles. maintain the nice work!
Data Science Courses in Bangalore

Business Analytics said...

I am sure it will help many people. Keep up the good work. It's very compelling and I enjoyed browsing the entire blog.
Business Analytics Course in Bangalore

AI Courses said...

What an incredible message this is. Truly one of the best posts I have ever seen in my life. Wow, keep it up.
AI Courses in Bangalore

Business Analytics said...

I am sure it will help many people. Keep up the good work. It's very compelling and I enjoyed browsing the entire blog.
Business Analytics Course in Bangalore

AI Courses said...

What an incredible message this is. Truly one of the best posts I have ever seen in my life. Wow, keep it up.
AI Courses in Bangalore

Business Analytics said...

I am sure it will help many people. Keep up the good work. It's very compelling and I enjoyed browsing the entire blog.
Business Analytics Course in Bangalore

s said...

sabyasachi lehenga is an Indian fashion designer from Kolkata. Since 1999, he has sold designer merchandise using the label Sabyasachi. Mukherjee is one of the Associate Designer Members of Fashion Design Council of India and the youngest board member of the National Museum of Indian Cinema. It is a dream of every girl to walk down the aisle in your vague bridal lehenga. Shop online the best of Sabyasachi Lehenga, Sabyasachi Sarees, Sabyasachi Anarkali & Sharara Set with Panache Haute Couture. Shop now with us online and avail the best of Sabyasachi Lehenga and give a dreamy start to your second inning of life.

Emerging Technologies said...

I need to thank you for this very good read and i have bookmarked to check out new things from your post. Thank you very much for sharing such a useful article and will definitely saved and revisit your site.
Data Science Course

Education said...

Your site is truly cool and this is an extraordinary moving article and If it's not too much trouble share more like that. Thank You..
Digital Marketing Institute in Bangalore

Institute said...

Wow, happy to see this awesome post. I hope this think help any newbie for their awesome work and by the way thanks for share this awesomeness, i thought this was a pretty interesting read when it comes to this topic. Thank you..
Artificial Intelligence Course

Knowledge said...

Thank a lot. You have done excellent job. I enjoyed your blog . Nice efforts
Cyber Security Course in Bangalore

aishu said...

Awesome post. I am glad to see your article. Very interesting to read your article. AWS Certification Course in Chennai

Micky said...

This is my first-time visit to your blog and I am very interested in the articles that you serve. Provide enough knowledge for me.
warehouse garage door repair in philadelphia

Data Science Chennai said...

I feel very grateful that I read this. It is very helpful and very informative and I really learned a lot from it.
Data Science Course in Chennai

Herry said...

So lucky to come across your excellent blog. Your blog brings me a great deal of fun. Good luck with the site.
commercial window replacement

Technology said...

All of these posts were incredible perfect. It would be great if you’ll post more updates and your website is really cool and this is a great inspiring article.
Artificial Intelligence course in Chennai

Data Science Courses said...

Awesome article. I enjoyed reading your articles. this can be really a good scan for me. wanting forward to reading new articles. maintain the nice work!
Data Science Courses in Bangalore

Institute said...

Wow, happy to see this awesome post. I hope this think help any newbie for their awesome work and by the way thanks for share this awesomeness, i thought this was a pretty interesting read when it comes to this topic. Thank you..
Artificial Intelligence Course

Data Science Chennai said...

I feel very grateful that I read this. It is very helpful and very informative and I really learned a lot from it.
Data Science Course in Chennai

Michael Oliver said...

Good blog,

Event Management Chennai, Event Management Companies in Chennai, Event Organisers Chennai, Birthday Party Organizers in Chennai, Wedding Planners in Chennai, Top 10 Event Management Companies Chennai, Best Event Management Company in Chennai

https://www.xquisiteevents.in/

Digital Vishnu said...

This is incredibly useful information!! Excellent work. All is very fascinating to learn and simple to grasp. Thanks for sharing such great info. Keep Post These kinds of Articles in the future.

Digital Marketing Course in Coimbatore
Digital Marketing Course Training in Tirupur
Digital Marketing Course Training in Madurai
Digital Marketing Course Training in Theni
Digital Marketing Training in Coimbatore

Technology said...

All of these posts were incredible perfect. It would be great if you’ll post more updates and your website is really cool and this is a great inspiring article.
Artificial Intelligence course in Chennai

Petersons said...

I wanted to thank you for this great read!! I definitely enjoying every little bit of it.I have you bookmarked to check out new stuff you post.


Los Angeles Garage Doors

Jerry said...

This is a wonderful article, Given so much info in it, These type of articles keeps the user's interest in the website.
commercial garage door replacement austin

Digital Marketing Course in Bangalore said...

It took a while to understand all the comments, but I really enjoyed the article. It turned out to be really helpful for me and I'm positive for all the reviewers here! It's always nice to be able to not only be informed, but also entertained! I'm sure you enjoyed writing this article.
Digital Marketing Course in Bangalore

Business Analytics Course said...

It would also motivate almost everyone to save this webpage for their favorite helper to help get the look published.
Business Analytics Course

Best Data Science Courses in Bangalore said...

I will very much appreciate the writer's choice for choosing this excellent article suitable for my topic. Here is a detailed description of the topic of the article that helped me the most.

Best Data Science Courses in Bangalore

Data Analytics Course in Bangalore said...

You have completed certain reliable points there. I did some research on the subject and found that almost everyone will agree with your blog.
Data Analytics Course in Bangalore

mokshamask said...

n95mask onlineand pollution mask are made to keep you safeguard from viruses, bacteria, dust, and other harmful particles. There are several types of face masks available in the market serving different purposes. Our n95 mask online is one of the most protective and laced with innovative technology available in the market at the lowest price. The replaceable n95 filter, washable cloth mask, silent fan, environment friendly, and cost-effective n95 mask online ensures soothing airflow without compromising safety.

Petersons said...

I wanted to thank you for this great read!! I definitely enjoying every little bit of it.I have you bookmarked to check out new stuff you post.


commercial garage door repair

Alvin Steve said...

This is a wonderful article, Given so much info in it, These type of articles keeps the user's interest in the website.
website cost

Petersons said...

Very informative site, i must bookmark it, keep posting interesting articles...


San Francisco Garage Door Repair

Michael Oliver said...

Good blog,

Digital Marketing Companies in Chennai, Website Design Companies in Chennai, SEO Companies in Chennai, Digital Marketing Company Chennai, Web Design Company Chennai

https://wisewebtek.com/

AI Courses said...

What an incredible message this is. Truly one of the best posts I have ever seen in my life. Wow, keep it up.
AI Courses in Bangalore

Business Analytics said...

I am sure it will help many people. Keep up the good work. It's very compelling and I enjoyed browsing the entire blog.
Business Analytics Course in Bangalore

Petersons said...

I wanted to thank you for this great read!! I definitely enjoying every little bit of it.I have you bookmarked to check out new stuff you post.


Window and Door Repair in Mississauga

Data Science Courses said...

Awesome article. I enjoyed reading your articles. this can be really a good scan for me. wanting forward to reading new articles. maintain the nice work!
Data Science Courses in Bangalore

AI Courses said...

What an incredible message this is. Truly one of the best posts I have ever seen in my life. Wow, keep it up.
AI Courses in Bangalore

Michael Oliver said...

Good blog,

ACCA Coaching Kerala, ACCA Coaching Center in Kerala, ACCA Classes in Kerala, ACCA Coaching Classes Kerala, Best ACCA Coaching in Kerala, No:1 ACCA Coaching Center in Kerala, Top 10 ACCA Coaching Centers in Kerala, ACCA Online Courses, ACCA Training, ACCA IFRS course, ACCA IFRS Certification, ACCA Online Coaching, ACCA Certification Courses, ACCA SBR Online Courses

https://ffacademia.com/

Data Analytics Course said...

Excellent Blog! I would like to thank you for the efforts you have made in writing this post. Gained lots of knowledge.
Data Analytics Course

Data Science Courses said...

Awesome article. I enjoyed reading your articles. this can be really a good scan for me. wanting forward to reading new articles. maintain the nice work!
Data Science Courses in Bangalore

Data Analytics Course said...

Excellent Blog! I would like to thank you for the efforts you have made in writing this post. Gained lots of knowledge.
Data Analytics Course

Petersons said...

I wanted to thank you for this great read!! I definitely enjoying every little bit of it.I have you bookmarked to check out new stuff you post.


garage door motor repair

Business Analytics said...

I am sure it will help many people. Keep up the good work. It's very compelling and I enjoyed browsing the entire blog.
Business Analytics Course in Bangalore

Knowledge said...

Thank a lot. You have done excellent job. I enjoyed your blog . Nice efforts
Data Science Certification in Hyderabad

Institute said...

Wow, happy to see this awesome post. I hope this think help any newbie for their awesome work and by the way thanks for share this awesomeness, i thought this was a pretty interesting read when it comes to this topic. Thank you..
Artificial Intelligence Course

Petersons said...

Very informative site, i must bookmark it, keep posting interesting articles...


central air conditioning

Emerging Technologies said...

I need to thank you for this very good read and i have bookmarked to check out new things from your post. Thank you very much for sharing such a useful article and will definitely saved and revisit your site.
Data Science Course

Petersons said...

I wanted to thank you for this great read!! I definitely enjoying every little bit of it.I have you bookmarked to check out new stuff you post.


Kitchen Star Houston

Data Science Training in Bangalore said...

You have completed certain reliable points there. I did some research on the subject and found that almost everyone will agree with your blog.

Data Science Training in Bangalore

Digital Marketing Training in Bangalore said...

Really wonderful blog completely enjoyed reading and learning to gain vast knowledge. Eventually, this blog helps in developing certain skills which in turn helpful in implementing those skills. Thanking the blogger for delivering such beautiful content and keep posting the contents in the upcoming days.

Digital Marketing Training in Bangalore

Education said...

Your site is truly cool and this is an extraordinary moving article and If it's not too much trouble share more like that. Thank You..
Digital Marketing Course in Hyderabad

Website Designing Company said...

Best Website Development Agency India

Petersons said...

I wanted to thank you for this great read!! I definitely enjoying every little bit of it.I have you bookmarked to check out new stuff you post.


commercial garage door repair

Machine Learning Course in Bangalore said...

The Extraordinary blog went amazed with the content that they have developed in a very descriptive manner. This type of content surely ensures the participants explore themselves. Hope you deliver the same near the future as well. Gratitude to the blogger for the efforts.

Machine Learning Course in Bangalore

Artificial Intelligence Training in Bangalore said...

I wanted to leave a little comment to support you and wish you the best of luck. We wish you the best of luck in all of your blogging endeavors.

Artificial Intelligence Training in Bangalore

Business Analytics said...

I am sure it will help many people. Keep up the good work. It's very compelling and I enjoyed browsing the entire blog.
Business Analytics Course in Bangalore

AI Courses said...

What an incredible message this is. Truly one of the best posts I have ever seen in my life. Wow, keep it up.
AI Courses in Bangalore

Petersons said...

I wanted to thank you for this great read!! I definitely enjoying every little bit of it.I have you bookmarked to check out new stuff you post.


scam warning

Website Designing Company said...

Flame Retardant Additives

Data Science Courses said...

Awesome article. I enjoyed reading your articles. this can be really a good scan for me. wanting forward to reading new articles. maintain the nice work!
Data Science Courses in Bangalore

Julli said...

I was exactly searching for. Thanks for such a post and please keep it up.
stratford management scam

Data Analytics Course said...

Excellent Blog! I would like to thank you for the efforts you have made in writing this post. Gained lots of knowledge.
Data Analytics Course

Petersons said...

I guess there's always an easier way ...


reputation management

Pradeep Appslure said...

Appslure is an award-winning mobile app development agency building feature-packed and interactive mobile applications for startups, medium and large enterprises.

Pradeep Appslure said...
This comment has been removed by the author.
360DigiTMGAurangabad said...

"Very Nice Blog!!!


Please have a look about "
data science courses aurangabad

Data Science Training in Bangalore said...

I bookmarked your website because this site contains valuable information. I am very satisfied with the quality and the presentation of the articles. Thank you so much for saving great things. I am very grateful for this site.

Data Science Training in Bangalore

Digital Marketing Training in Bangalore said...

I have voiced some of the posts on your website now, and I really like your blogging style. I added it to my list of favorite blogging sites and will be back soon ...

Digital Marketing Training in Bangalore

360DigiTMGAurangabad said...

Wow, amazing post! Really engaging, thank you.
data scientist course in aurangabad

«Oldest ‹Older   601 – 800 of 1001   Newer› Newest»