Giter VIP home page Giter VIP logo

Comments (11)

jruts avatar jruts commented on August 19, 2024 6

@msqaddura really... all I want to do is open a discussion where we could all learn from, yet you fail to address anything I mentioned in my comment and post a picture of what AtScript is?

I do sense you are being very defensive but fail to come up with real examples or benefits. Even the examples you post in pure javascript clearly indicate that you have no great experience with pure javascript at all.

All I was hoping for was a conclusion to my question as to why would I ever use a builder pattern as a javascript developer. There is no need for childish discussion or immature responses.

from design_patterns_in_typescript.

jruts avatar jruts commented on August 19, 2024 3

@msqaddura , in javascript you have the choice to do OOP or functional. And I think you are missing the point. I was trying to find an answer to the following question:

Why would you use a builder pattern when using plain javascript object literals gives you the same readability and the same functionality, but without any of the overhead or boilerplate.

I am not trying to attack any patterns here, I just do not think it belongs in every language. And since TypeScript is merely a superset of javascript, it is still javascript.

And as per definition of the builder pattern, the problem it is trying to solve is not present in javascript.

from design_patterns_in_typescript.

jruts avatar jruts commented on August 19, 2024 3

@msqaddura you lost me at 'superior constructor'.

Favor composition over class inheritance

Never would I fall in the trap of extending, so never would I have the issue you just described.

And your example is again an example of how a Java person would write node. Just take a look at the 'request' module and see how it is done generally in node: https://github.com/request/request

// You would do:
request.get({
  host: 'localhost',
  port: 9999,
  path: 'mypaeh'
}, callback)

// not
new Get("http","myPath","localHost",9999)

The only reason why you are finding these issues is because you are not coming up with common nodejs/javascript examples. You find the problems by using javascript as if it was java.

from design_patterns_in_typescript.

jruts avatar jruts commented on August 19, 2024 1

I would never use a class in the first place when a simple object literal and simple functions can do the job. hence I do not need to create anything with the new keywords. Don't forget this is JavaScript. It does not have to be or look like Java

from design_patterns_in_typescript.

msqaddura avatar msqaddura commented on August 19, 2024 1

man I believe you are completely out of the context between Prototyping(apparently your style), Object Oriented(apparently not your style), Functional(everyone's style that doesnt really matter)... what am saying is just that for you and the way you look at javascript (over a typescript code) you do not need any pattern it wont help you anyway... unless you are hardcore Object Oriented with javascript/typescript then you can use a pattern but for you it is absolutely no point to bother about a pattern.

just because there is a pattern it doesnt really mean that we have to use it everywhere... it can only make things worse if we are forcing it into something that is not meant for it.

from design_patterns_in_typescript.

jruts avatar jruts commented on August 19, 2024 1

Typescript is a superset of javascript. Which means plain javascript is valid typescript. The benefit that typescript gives you is nice IDE support like auto-completion and compile errors. You could easily write a definition for the object literal you want to pass along and it would compile to valid javascript with the typescript benefits.

But let's make it very clear, adding typescript does not mean this language becomes Java and it does not mean you should treat it in the same way.

By adding typescript for it's benefits to then add all the complexity of design patterns you do not need kinda defeats the purpose for me.

The builder pattern does not solve any problems that exist in javascript or typescript for that matter.

from design_patterns_in_typescript.

0xphilipp avatar 0xphilipp commented on August 19, 2024 1

Even though the last comment was quite long ago, but I just stumbled across this question.
In my opinion it also adds a lot of value in the javascript/typescript world. Of course it is dependent on the use case if it is usefull or not.

Here are the advantages:

Decouples the model of the creation of the model.

If your model changes often, you don't need to change as many places. -> Clearer git history on business files, less conflicts due to refactorings.

Radability is improved

Readability is especially improved, if you have a huge object with a lot of properties and when you create a lot of elements through the builder:

If you take a look at the example, that this dense code would need for each of the method chains at least 1-2 more lines, it is harder too read.
image

Context

A real builder can have multiple sub builders, that depend on the called method. In the example above for the first call you have different possibilities of initialization, which will change some fundamental things.

Extensibility / Transformations

The builder can add very usefull utilities to make the usage of the model a lot easier. A junior dev might not know dependencies between different properties of the model. But they can be encapsulated into a nice api using a builder.

They can set multiple properties (also with good default values specially for these calls)
image

They can set pre defined values
image

They can even extend the usages, by allowing transformation of inputs. This way the model does not need to be extended, as long as we can map to the result in some way:

image


I hope this makes it clear, that there are indeed use cases for such a pattern.

Btw. jQuery is a huge builder pattern. (https://www.w3schools.com/jquery/jquery_chaining.asp)

from design_patterns_in_typescript.

TomSeldon avatar TomSeldon commented on August 19, 2024

One use case I've come across (I'm going to try and dig up a really good blog post about this as well), is for when creating mock data in unit tests.

I used to do this very much like your above example.

e.g.

let createUser;

beforeEach(() => {
    createUser = () => {
        return {
            username: 'bob.smith',
            email: '[email protected]',
            accountType: ACCOUNT_TYPES.DEVELOPER
       };
    };  
}));

// some spec

it('should do something', () => {
    const user = createUser();
});

This is all well and good, but what if we don't always want to test against a "developer" user. Well, we could do something like you suggested and pass in an object to override the parameters, or use individual parameters (e.g. createUser => (username) => {}).

This is fine, but if you often find yourself having to modify the default/generic object in order to obtain a useful object to test against, you can end up with lots of:

const user = createUser({
    accountType: ACCOUNT_TYPES.ADMIN,
    username: 'some.user'
});

// ...

const user = createUser({
    accountType: ACCOUNT_TYPES.ADMIN,
    username: 'some.user'
});

// ...etc...

That seems fine in isolation, but if each of those definitions is really saying "create me an admin user", then that would be better abstracted to a createAdminUser function, which sets the admin defaults and allows overrides, similar to createUser.

In a simple example like this, it's probably more overhead that it's worth to do anything more complicated than that.

If, such as in a real, complicated application, you're needing to create users in a lot of different places (read: a lot of different tests), the above can quickly get repetitive and you can end up with lots of these types of functions littered through the test suite. In such a situation, having a generalised "userBuilder" can help reduce duplication through the tests.

Much of this can be applicable to non-test code, too, but I'm specifically focussing on that as it's what I found most useful.

Apologies for the slight incoherence, trying to type out this quickly during the downtime of waiting for something to compile...

A really good blog post on this is: http://davedevelopment.co.uk/2015/01/28/test-data-builders.html

The examples in that blog post are all PHP, but it's just as relevant here. Especially if you want to work with immutable data (though not a prerequisite to this being useful).


TL;DR: For a very small or very simple use cases, it introduces overhead that almost certainly isn't worth it. But the same can be said of most abstractions. (One of?) the benefits comes with reducing complexity and repetitiveness in larger and more complicated use cases.

from design_patterns_in_typescript.

jruts avatar jruts commented on August 19, 2024

Thanks for the quick response!

I am kinda struggling to see where a builder would be easier for testing.
Similar to where I have to create my object to create a user, you would also have to build your object with the builder, which is just an abstraction of creating the object anyway.

so instead of:

const user = createUser({
    accountType: ACCOUNT_TYPES.ADMIN,
    username: 'some.user'
});

you would need to do something like:

const user = User(User.Builder('some.user').withAccountType(ACCOUNT_TYPES.ADMIN))

So I do not see the benefit of that in testing.
If I needed a specific admin user for multiple tests, I would just create an admin user with the correct options.
You would also need to create this admin user if you were to use the builder pattern.

So yes, I am still struggling to see 'why' :)

Btw small addition to your test code to make it more flexible:

let createUser;

beforeEach(() => {
    createUser = options => {
        const defaultUser = {
           username: 'bob.smith',
           email: '[email protected]',
           accountType: ACCOUNT_TYPES.DEVELOPER
        }

        return Object.assign({}, defaultUser, options);
    };  
}));

// some spec

it('now you can do stuff like this:', () => {
  // default user
  const user = createUser();

  // different email
  const otherUser = createUser({email: 'another email'})
});

from design_patterns_in_typescript.

msqaddura avatar msqaddura commented on August 19, 2024

https://github.com/joelpalmer/Typescript--Builder-Pattern
please look at this example it should completely answer your original question that we drifted from.
var myRequest = new scope.Utils.RequestBuilder("get").setScheme("http").setPath("mypath").setHost("localhost").setPort("9999").build();

without a builder it would be
var myRequest = new Get("http","myPath","localHost",9999)
and cards constructor would be constructor(Scheme="http",path="myPath"......)

we can add destructing pattern over here for scrambled values where order doesnt matter
constructor({Scheme="http",...})//ntices we wrapped it weith json tab

so yes you can fiddle it down to literal objects but once change in superior constructor will have to be done to all constructors super() call... but with builder you would just need to change the method in the superior class... again you can find a way to simplify so it is always like this... you can always find your way out

from design_patterns_in_typescript.

Kumjami avatar Kumjami commented on August 19, 2024

typescript adds types to javascript, it doesn't mean you have to forget about javascript essence

the same question can be done in a javascript page where described a builder pattern, or typescript, because the issue is the same, and the problem it faces/solves is the same

from design_patterns_in_typescript.

Related Issues (6)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.