Number of function parameter

103 views
Skip to first unread message

Radoslaw Grymin

unread,
Jun 13, 2017, 5:21:38 AM6/13/17
to Clean Code Discussion
Hello!

Uncle Bob told that he prefers setters rather than constructors with many arguments.
How it deals with RAII pattern? And what when programmer don't remember about setting some attribute? Object will have inproper state.
 In RAII approach we want all atributes initialized in constructor, all removed in destructor. No place for doing that during runtime.

Best regards,
Radosław Grymin

PS: We shell make this group alive. It is a great place for self-development

Caio Fernando Bertoldi Paes de Andrade

unread,
Jun 13, 2017, 8:22:03 AM6/13/17
to clean-code...@googlegroups.com
Hello Radoslaw, and welcome to the group!

I personally prefer to have all arguments on the constructor, and to mitigate the “too many arguments on the constructor” problem, I like to write factory methods or classes. That way I can provide to my user methods to create the object with as little as only the mandatory arguments, and as complete as including all optional parameters.

Sometimes having too many arguments on the constructor is a symptom of a deeper design problem, like Feature Envy, for example, so always keep an eye open to that.

Hope this helps!
Caio

--
The only way to go fast is to go well.
---
You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discu...@googlegroups.com.
To post to this group, send email to clean-code...@googlegroups.com.
Visit this group at https://groups.google.com/group/clean-code-discussion.

Radoslaw Grymin

unread,
Jun 17, 2017, 8:12:36 AM6/17/17
to Clean Code Discussion, caio...@icloud.com
Thank you Caio for your response.

Maybe factories help with number of parameters. But I still feel that it doesn't help at all. I have to invoke constructor inside the factory.
Calling setters instead of constructors for me is a bad idea. I feel that it can violate tell-don't-ask principle.
I like to construct objects in desired state, not in the default state. What if I forget about a setter? Class will be left in the wrong state.

Maybe if I have too many parameters in constructor it can inform me that I may have a superclass and I need to divide it to smaller classes.

So I think, maybe "too many parameters problem" should be adressed for users of libraries. Sometimes it may be impossible to have two
parameters everywhere in the code but it would be nice to provide an interface for users of our library that is not 'overloaded' with too many function parameters.

What do you think abut such solution?

Radek 

W dniu wtorek, 13 czerwca 2017 14:22:03 UTC+2 użytkownik Caio Fernando Bertoldi Paes de Andrade napisał:
Hello Radoslaw, and welcome to the group!

I personally prefer to have all arguments on the constructor, and to mitigate the “too many arguments on the constructor” problem, I like to write factory methods or classes. That way I can provide to my user methods to create the object with as little as only the mandatory arguments, and as complete as including all optional parameters.

Sometimes having too many arguments on the constructor is a symptom of a deeper design problem, like Feature Envy, for example, so always keep an eye open to that.

Hope this helps!
Caio
On 11 Jun 2017, at 19:16, Radoslaw Grymin <rgr...@gmail.com> wrote:

Hello!

Uncle Bob told that he prefers setters rather than constructors with many arguments.
How it deals with RAII pattern? And what when programmer don't remember about setting some attribute? Object will have inproper state.
 In RAII approach we want all atributes initialized in constructor, all removed in destructor. No place for doing that during runtime.

Best regards,
Radosław Grymin

PS: We shell make this group alive. It is a great place for self-development

--
The only way to go fast is to go well.
---
You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discussion+unsub...@googlegroups.com.

Jacek Bilski

unread,
Jun 17, 2017, 11:26:23 AM6/17/17
to clean-code...@googlegroups.com
Hi Radek,

On 17.06.2017 14:12, Radoslaw Grymin wrote:
> Thank you Caio for your response.
>
> Maybe factories help with number of parameters. But I still feel that it
> doesn't help at all. I have to invoke constructor inside the factory.
> Calling setters instead of constructors for me is a bad idea. I feel
> that it can violate tell-don't-ask principle.
> I like to construct objects in desired state, not in the default state.
> What if I forget about a setter? Class will be left in the wrong state.

Against forgetting to call a setter you can use TDD. Also, for too many
parameters, builder might be a more appropriate approach. I cannot tell,
because you didn't mention what this class is, is there any hierarchy,
etc. So, unfortunately, the answer is: it depends.

> Maybe if I have too many parameters in constructor it can inform me that
> I may have a superclass and I need to divide it to smaller classes.

That's actually first thing I'd do, try to find out if all those fields
need to go together, maybe there are two or more sets of them serving
different actors. Then "divide and conquer", make your problem smaller,
hopefully to a point, where it doesn't hurt.

> So I think, maybe "too many parameters problem" should be adressed for
> users of libraries. Sometimes it may be impossible to have two
> parameters everywhere in the code but it would be nice to provide an
> interface for users of our library that is not 'overloaded' with too
> many function parameters.

I'm not certain I understood you. Heavily overloaded functions look like
a thing good for libraries, the authors don't know how this library
might be used. If you're writing code for yourself, then opening up so
much might be a YAGNI violation.

--
Pozdrawiam / Best regards / Mit freundlichen Grüßen

Jacek Bilski

Radoslaw Grymin

unread,
Jun 17, 2017, 4:07:19 PM6/17/17
to clean-code...@googlegroups.com
Hi Jacek,

in the Episode No. E04 (Function Structure) Uncle Bob told a generic rule - he limits number of function arguments in his programs to 3. 
And It is a little bit confusing. It is really difficult to achieve. I dont consider particular program, I think about programs overall, about this rule of thumb.

Yes, I can achieve it by removing parameters from constructor and create setters. But if I set attributes separately it may lead to logical inconsistency.
And if I want to check if the state is proper, I need to know about relations between class atributes - as a class user I should not think about it.
Ok, I can make checks in setters and throw exceptions.
But still, users of this class will have to remember that before invoking method they need to call setter.
I think that TDD is the great invent and I use it when it is possible (if test compilation does not last many minutes, in C++ it is a big problem, preprocessor has lot to do...),

but still, as a class user I don't want to remember about setting class state after construction.

So, for me this rule is not possible to fulfiled everytime.

I wanted to ask you if you follow this rule and if you have some techniques how to achieve it. And what do you think about setters (instead of many parameters of constructor),
proposed by Uncle Bob.

Best regards,
Radek

Jon Reid

unread,
Jun 17, 2017, 5:22:20 PM6/17/17
to clean-code...@googlegroups.com
I think the way to use this "no more than 3" pressure is to ask, do I need to use the Introduce Parameter Object refactoring?

Jon Reid
Jon Reid
Quality Coding
Twitter Facebook GitHub

--
The only way to go fast is to go well.
---
You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discu...@googlegroups.com.

Jacek Bilski

unread,
Jun 17, 2017, 5:58:52 PM6/17/17
to clean-code...@googlegroups.com


On 17.06.2017 22:07, Radoslaw Grymin wrote:
> Hi Jacek,
>
> in the Episode No. E04 (Function Structure) Uncle Bob told a generic
> rule - he limits number of function arguments in his programs to 3.
> And It is a little bit confusing. It is really difficult to achieve. I
> dont consider particular program, I think about programs overall, about
> this rule of thumb.
>
> Yes, I can achieve it by removing parameters from constructor and create
> setters. But if I set attributes separately it may lead to logical
> inconsistency.
> And if I want to check if the state is proper, I need to know about
> relations between class atributes - as a class user I should not think
> about it.
> Ok, I can make checks in setters and throw exceptions.
> But still, users of this class will have to remember that before
> invoking method they need to call setter.
> I think that TDD is the great invent and I use it when it is possible
> (if test compilation does not last many minutes, in C++ it is a big
> problem, preprocessor has lot to do...),
>
> but still, as a class user I don't want to remember about setting class
> state after construction.
>
> So, for me this rule is not possible to fulfiled everytime.

Exactly, what I've learned so far about software development is, that
it's an art of trade-offs. If having no more than 3 parameters is the
most important rule for you, you might need to sacrifice something else,
like ensuring consistent state of objects. And it's your, usually
difficult, choice to make: which of all the rules you know is more
important. Tricky part is, everyone would probably be doing different
trade-offs. In this case I personally would easily sacrifice "max 3
parameters" rule to get consistent objects.

> I wanted to ask you if you follow this rule and if you have some
> techniques how to achieve it. And what do you think about setters
> (instead of many parameters of constructor),
> proposed by Uncle Bob.

Yes, I'm trying to follow that rule. How do I achieve it? Sometimes I
don't. Sometimes I'm using builders for more complicated objects.
Sometimes I split objects, because I realize they're too big (if I may
notice, I have a feeling you're carefully omitting this advice from Caio
and me, maybe try to see if your object can be broken). As usual: it
depends.

Andrés Moya

unread,
Jun 17, 2017, 8:41:20 PM6/17/17
to clean-code...@googlegroups.com
I think that the "no more than 3 parameters" rule, perhaps, doesn't apply to class constructors. These are not normal functions, they can even be actually different beasts, like in Meyer's Eiffel language.

If an object cannot be partitioned and it makes sense for it to have many fields, i see no problem to write a constructor with so many parameters.

--
The only way to go fast is to go well.
--- You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discussion+unsubscri...@googlegroups.com.
To post to this group, send email to clean-code-discussion@googlegroups.com.



--
 
Andrés Moya Velázquez  
Engineer

www.kaleidos.net

Oleksii Fedorov

unread,
Jun 18, 2017, 5:10:15 AM6/18/17
to clean-code...@googlegroups.com
I personally use "too much constructor parameters" as a cue to spot SRP violation. If the object knows about too much other objects, then it has too much responsibility.

I solve it by introducing more objects, that depend and coordinate some of the original dependencies of these original class. Then I use these higher level objects from the original class.

Sometimes such refactoring is easy because responsibilities are fairly separate already inside of the class. Other times it is a very hard refactoring because responsibilities are seriously intertwined.

An interesting example of refactoring I was doing lately:

Initially, class GamePresenter had lots of dependencies (and therefore constructor parameters):
- router
- presentable
- presentableModel
- userCurrencyPresenter
- game
- selectLetterService
- selectInputLetterService
- resetGameService
- promptRevealLetterService
- promptRemoveInvalidLettersService

First of all, I had to split presentable and presentableModel in 4 slices, as they were basically presenting *everything* there is to present in the application. Ended up with: userCurrencyPresentable, messagePresentable, gameStatusPresentable, letterStatusPresentable.

That enabled me to split the GamePresenter class into different classes, each responsible for presenting only a few things. Also, GamePresenter was doing much more than just presenting, it was actually a collection of use case classes. So I've split it up into use cases instead of presenters:

- StartGameUseCase (what startPresentation() function was doing)
  - currently depends on: userCurrencyPresenter, router, game and presentable;
  - refactoring: make it depend on startGamePresenter and game.
    - startGamePresenter will depend on userCurrencyPresenter and levelPresenter
      - userCurrencyPresenter will depend on router

- SelectLetterUseCase (what select(letter) was doing)
  - if Presentable is split as aforementioned, it would depend on: letterStatusPresenter, errorPresenter, gameStatusPresenter, selectLetterService, and a weird showPresentableModel function
  - refactoring: make it depend on selectLetterPresenter and selectLetterService
    - selectLetterPresenter should depend on letterStatusPresenter, errorPresenter and interface extracted from weird showPresentableModel function, that is specific to this use case
    - dependency on gameStatusPresenter should move to FinishGameUseCase or FinishLevelUseCase because SelectLetterUseCase should not finish game or level, it should somehow trigger another use case to do the thing. This refactoring may be very hard

- SelectInputUseCase (what select(input) was doing)
- AdvanceToNextLevelUseCase (what advanceToNextLevel() was doing)
- PromptRevealLetterUseCase (what promptRevealLetterAction() was doing)
- PromptRemoveInvalidLettersUseCase (what promptRemoveInvalidLettersAction() was doing)
- FinishGameUseCase (what finishGameAction() was doing)

I'll not provide all the details for other use cases because it is a lot of things to go through. But I think you get the gist of what I was doing there from the first two examples. These use cases are now wired to appropriate user actions in appropriate places of the program.

Kind regards,

To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discu...@googlegroups.com.
To post to this group, send email to clean-code...@googlegroups.com.
--
 
Andrés Moya Velázquez  
Engineer

www.kaleidos.net

--
The only way to go fast is to go well.
---
You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discu...@googlegroups.com.
To post to this group, send email to clean-code...@googlegroups.com.
--
Oleksii Fedorov
Software Engineer, Consultant, and Crafter,
Adept of Depth in a world of Shallow,
I care about software developers' productivity and software quality,
I teach software developers how to negotiate promotions, increase productivity, and handle stress. Grab my "war stories" to learn how to get paid what you're worth and do work that matters:

Martin Lee

unread,
Jun 18, 2017, 7:22:59 PM6/18/17
to Clean Code Discussion
Aside from the probable SRP violation indicated by too many member variables [read: split classes up first]...

For me "i3" ("instantiation is initialisation") is important, constructor takes everything required. Avoiding setters is [closer to] Functional programming, therefore probably more robust, and mandatory if you are trying to make the rest of the class Functional too.
Another way to think about it => build a class or a data structure - do not mix.
Therefore setters are to be avoided on behavioral classes - as opposed to data structures. (imho)

TDD does not address classes at the fringe of your application - ie. the Public classes of a lib/api. Why force users of your public classes to write tests they don't need. "i3" guarantees consistent initialisation without additional tests.
Reply all
Reply to author
Forward
0 new messages